<template>
	<table v-if="(resultset) && (resultset.length > 0)" class="table">
		<thead>
			<tr><th v-for="x in dow">{{x}}</th></tr>
		</thead>
		<tbody>
			<tr v-for="week in resultset">
				<td v-for="day in [0, 1, 2, 3, 4, 5, 6]" class="datebox">
					<template v-if="week.values[day]">
						<div class="datebox" :style="{ backgroundColor: resultset.max > 0 ? 'rgba(220, 53, 69, ' + week.values[day].length/resultset.max + ')' : null }"><span class="occupancy hidden">#{{week.values[day].length}}</span> {{day > 0 ? week.values[day][0]._START_OBJ.getDate() : week.key.toLocaleDateString('sv-SE')}} <span class="occupancy">#{{week.values[day].length}}</span></div>
						<template v-for="appointment in week.values[day]">
							<div v-if="appointment._BREAK" class="vacancy" :title="appointment._START_OBJ.toLocaleTimeString('en-GB').substring(0, 5) + '–' + appointment._END_OBJ.toLocaleTimeString('en-GB').substring(0, 5)" />
							<div v-else :title="appointment._START_OBJ.toLocaleTimeString('en-GB').substring(0, 5) + '–' + appointment._END_OBJ.toLocaleTimeString('en-GB').substring(0, 5) + '\n' + appointment.PATIENTNAME + ' ' + appointment.HRN.slice(-4) + '\n' + appointment.NOTE"><span v-if="appointment._CONCURRENCY > 0" class="concurrency hidden">*<template v-if="appointment._CONCURRENCY > 1">{{appointment._CONCURRENCY}}</template></span>{{appointment._START_OBJ.toLocaleTimeString('en-GB').substring(0, 5)}} <router-link :to="'/patient/' + appointment.PATIENTID">{{appointment.PATIENTNAME.substring(0, 1)}}{{appointment.HRN.slice(-4)}}</router-link><span v-if="appointment._CONCURRENCY > 0" class="concurrency">*<template v-if="appointment._CONCURRENCY > 1">{{appointment._CONCURRENCY}}</template></span></div>
						</template>
					</template>
					<div v-else class="datebox">{{day > 0 ? (new Date(week.key.getTime() + 1000*60*60*24*day)).getDate() : week.key.toLocaleDateString('sv-SE')}}</div>
				</td>
			</tr>
		</tbody>
	</table>
</template>

<style scoped>
	table {
		font-family: monospace;
		text-align: center;
	}
	tbody, td {
		border: 1px solid #dee2e6;
	}
	div.datebox {
		font-weight: bold;
	}
	div.vacancy {
		width: 2em;
		margin: auto;
		border-bottom: 0.25em dotted #bbb;
	}
	span.occupancy {
		font-weight: normal;
	}
	span.concurrency {
		font-weight: bold;
	}
	span.hidden {
		visibility: hidden;
	}
</style>

<script>
	import { groupBy, groupByArray, strfdate_vista, debounce } from './util.mjs';

	const C_DAY = 1000*60*60*24;
	const C_WEEK = C_DAY*7;

	function dateonly(date) {
		return new Date(date.getFullYear(), date.getMonth(), date.getDate());
	}

	function infill_weeks(res, date_begin, date_end) {
		for(var i = res.length - 1; i > 0; --i) {
			var cur = res[i], prev = res[i - 1];
			while(cur.key - prev.key > C_WEEK) res.splice(i, 0, cur = { key: new Date(cur.key.getTime() - C_WEEK), values: [] });
		}
		var item;
		if(res.length < 1) res.push({ key: date_begin, values: [] });
		else {
			item = res[0];
			while(item.key - date_begin >= C_WEEK) res.splice(0, 0, item = { key: new Date(item.key.getTime() - C_WEEK), values: [] });
		}
		item = res[res.length - 1];
		while(date_end - item.key >= C_WEEK) res.push(item = { key: new Date(item.key.getTime() + C_WEEK), values: [] });
		return res;
	}

	function analyze_week(res) {
		for(var k in res) if(res.hasOwnProperty(k)) analyze_day(res[k]);
		return res;
	}

	function analyze_day(res) {
		for(var i = res.length - 1; i > 0; --i) {
			var item = res[i];
			item._CONCURRENCY = 0;
			for(var j = i - 1; j >= 0; --j) if(item._START_OBJ < res[j]._END_OBJ) item._CONCURRENCY++;
			if((item._CONCURRENCY < 1) && (item._START_OBJ > res[i - 1]._END_OBJ)) res.splice(i, 0, { _BREAK: true, _START_OBJ: res[i - 1]._END_OBJ, _END_OBJ: item._START_OBJ });
		}
		return res;
	}

	export default {
		props: {
			client: Object,
			resource: String,
			date_begin: Date,
			date_end: Date
		},
		data() {
			var now = new Date();
			return {
				resultset: [],
				dow: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
			};
		},
		created() {
			this.$watch(
				() => (this.client, this.resource, this.date_begin, this.date_end, {}),
				debounce(async () => {
					if((this.client) && (this.resource) && (this.date_begin) && (this.date_end)) {
						var date_begin = new Date(this.date_begin.getTime() - C_DAY*this.date_begin.getDay()), weekref = date_begin;
						var date_end = new Date(this.date_end.getTime() + C_DAY*(6 - this.date_end.getDay()));
						var resultset = (await this.client.SDEC_CRSCHED(this.resource, strfdate_vista(date_begin), strfdate_vista(date_end) + '@2359')).filter(x => (x.CANCELLED == '0') && (x.NOSHOW == '0')).map(x => {
							var _START_OBJ = x._START_OBJ = new Date(x.START_TIME);
							x._START_DATE = _START_OBJ.toLocaleDateString('sv-SE');
							x._END_OBJ = new Date(x.END_TIME);
							x._WEEK_DAY = _START_OBJ.getDay();
							x._WEEK_NUM = Math.floor((x._START_OBJ - weekref)/(C_WEEK));
							return x;
						}).sort((a, b) => a._START_OBJ - b._START_OBJ);
						this.resultset = infill_weeks(groupByArray(resultset, '_WEEK_NUM').map(week => ({ key: new Date(weekref.getTime() + C_WEEK*week.key), values: analyze_week(groupBy(week.values, '_WEEK_DAY')) })), date_begin, date_end);
						this.resultset.max = Math.max.apply(null, groupByArray(resultset, '_START_DATE').map(x => x.values.length));
					} else this.resultset = [];
				}, 500),
				{ immediate: true }
			);
		}
	};
</script>
