<template>
	<div>
		<label class="form-check form-check-inline form-switch form-check-label" v-for="report in reports">
			<input class="form-check-input" type="checkbox" v-model="report.selected" /> {{report.name}}
		</label>
		<label class="form-check form-check-inline form-switch form-check-label">
			<input class="form-check-input" type="checkbox" v-model="calculate" /> Calculate
		</label>
	</div>
	<ViewData :resultset="resultset" :daily="true" :constants="calculate ? constants : []" :calculations="calculate ? calculations : []" :reports="reports_selected" />
</template>

<script>
	import { strftime_vista, strptime_vista } from './util.mjs';

	import ViewData from './ViewData.vue';

	const time_min = new Date(1700, 0, 1);

	const calculations = [
		{ name: 'Age', unit: 'yr', deps: ['Time', 'DOB'], calc(Time, DOB, prev) { var x = Math.floor((Time - DOB.getTime())/3.15576e10); return x != prev ? x : undefined; } },
		{ name: 'BMI', unit: 'kg/m²', rangeL: 18.5, rangeH: 24.9, range: '18.5 - 24.9', deps: ['Ht', 'Wt'], calc: (Ht, Wt) => (10000*Wt/(Ht*Ht)).toPrecision(3) },
		{ name: 'BSA', unit: 'm²', deps: ['Ht', 'Wt'], calc: (Ht, Wt) => (0.007184*Math.pow(Ht, 0.725)*Math.pow(Wt, 0.425)).toPrecision(3) },
		{ name: 'CrCl', unit: 'mL/min', deps: ['Age', 'Sex', 'Wt', 'CREATININE'], calc: (Age, Sex, Wt, CREATININE) => (((140 - Age) * Wt)/(72*CREATININE)*(Sex == 'M' ? 1 : 0.85)).toPrecision(4) },
		{ name: 'RETICYLOCYTE#', unit: 'K/cmm', rangeL: 50, rangeH: 100, range: '50 - 100', deps: ['RBC', 'RETICULOCYTES'], calc: (RBC, RETICULOCYTES) => (10*RBC*RETICULOCYTES).toPrecision(3) },
		{ name: 'CALCIUM CORRECTED', unit: 'mg/dL', rangeL: 8.9, rangeH: 10.3, range: '8.9 - 10.3', deps: ['CALCIUM', 'ALBUMIN'], calc: (CALCIUM, ALBUMIN) => ALBUMIN < 4 ? (+CALCIUM + 0.8*(4 - ALBUMIN)).toPrecision(3) : undefined },
		{ name: 'IRON SATURATION', unit: '%', rangeL: 15, rangeH: 55, range: '15 - 55', comment: 'IRON/TIBC', deps: ['IRON', 'TIBC'], calc: (IRON, TIBC) => (100*IRON/TIBC).toPrecision(3) },
	];

	const reports = [
		{ name: 'Vitals', value: ['T', 'P', 'R', 'SBP', 'DBP', 'Pulse Oximetry', 'Wt', 'Ht', 'BMI', 'BSA', 'Pain'], selected: true },
		{ name: 'CBC', value: ['HGB', 'MCV', 'RETICYLOCYTE#', 'PLT', 'WBC', 'NEUTROPHIL#'], selected: false },
		{ name: 'Renal', value: ['CREATININE', 'UREA NITROGEN', 'EGFR CKD-EPI 2021', 'Estimated GFR dc\'d 3/30/2022', 'CrCl'], selected: false },
		{ name: 'Hepatic', value: ['SGOT', 'SGPT', 'LDH', 'ALKALINE PHOSPHATASE', 'GAMMA-GTP', 'TOT. BILIRUBIN', 'DIR. BILIRUBIN', 'ALBUMIN'], selected: false },
		{ name: 'Electrolytes', value: ['SODIUM', 'CHLORIDE', 'CO2', 'CALCIUM', 'CALCIUM CORRECTED', 'IONIZED CALCIUM (LABCORP)', 'POTASSIUM', 'MAGNESIUM', 'PO4', 'ANION GAP', 'OSMOBLD'], selected: false },
		{ name: 'Coagulation', value: ['PT', 'INR', 'PTT'], selected: false },
		{ name: 'Vitamins', value: ['FERRITIN', 'IRON', 'TIBC', 'IRON SATURATION', 'B 12', 'FOLATE', 'VITAMIN D TOTAL 25-OH'], selected: false },
		{ name: 'Thyroid', value: ['TSH', 'T4 (THYROXINE)'], selected: false },
		{ name: 'Myeloma', value: ['PROTEIN,TOT SER (LC)', 'ALBUMIN [for SPEP](LC)', 'ALPHA-1 GLOBULIN S (LC)', 'ALPHA-2 GLOBULIN S (LC)', 'BETA GLOBULIN S (LC)', 'GAMMA GLOBULIN S (LC)', 'GLOBULIN,TOTAL S (LC)', 'A/G RATIO S (LC)', 'M-SPIKE S (LC)', 'IMMUNOFIXATION SERUM (LC)', 'FREE KAPPA LT CHAIN, S (LC)', 'FREE LAMBDA LT CHAIN, S (LC)', 'KAPPA/LAMBDA RATIO, S (LC)', 'KLRATIO', 'IMMUNOGLOBULIN G,QN (LC)', 'IMMUNOGLOBULIN A,QN (LC)', 'IMMUNOGLOBULIN M,QN (LC)', 'IGG', 'IGA', 'IGM', 'ALBUMIN [for RAND UR](LC):U', 'ALPHA-1 GLOB RAND UR(LC):U', 'ALPHA-2 GLOB RAND UR(LC):U', 'BETA GLOB RAND UR(LC):U', 'GAMMA GLOB RAND UR(LC):U', 'M-SPIKE% RAND UR(LC):U', 'PROTEIN,TOT UR(LC):U', 'FKLCUR:U', 'FLLCUR:U', 'KAPPA/LAMBDA RATIO, UR (LC):U', 'KLRATIO:U', 'PROTEIN,24H CALC(LC):U', 'ALBUMIN [for 24UPEP](LC):U', 'ALPHA-1 GLOBULIN 24H(LC):U', 'ALPHA-2 GLOBULIN 24H(LC):U', 'BETA GLOBULIN 24H(LC):U', 'GAMMA GLOBULIN 24H(LC):U', 'M-SPIKE% 24H(LC):U', 'M-SPIKE mg/24hr(LC):U', 'FR KAPPA LTCH:U', 'FR LAMBDA LTCH:U'], selected: false }
	];
	reports.reduce((acc, x) => acc[x] = x, reports);

	const vitals_mapping = {
		'T': { range: '35 - 38' },
		'P': { range: '60 - 100', unit: 'bpm' },
		'R': { range: '12 - 19', unit: 'bpm' },
		'Pulse Oximetry': { range: '95 - 100' }
	};

	function vitals_normalize(rs) {
		return rs.map(function(x) {
			var comment = x.comment && x.comment.replace(/^\s+|\s+$/g, '').replace(/\s+/g, ' ');
			var res = {
				time: x.datetime,
				name: x.name,
				unit: x.unit,
				value: x.value,
				flag: x.flag,
				comment: comment ? x.user + ' • ' + comment : x.user
			};
			return vitals_mapping[x.name] ? Object.assign(res, vitals_mapping[x.name]) : res;
		});
	}

	function labs_normalize(rs) {
		return rs.map(function(x) {
			var specimen = x.specimen;
			return {
				time: x.time_collected,
				name: (specimen == 'BLOOD') || (specimen == 'SERUM') || (specimen == 'PLASMA') ? x.name : (specimen == 'RANDOM URINE') ? x.name + ':UR' : specimen ? x.name + ':' + specimen.charAt(0) : x.name,
				unit: x.unit,
				range: x.range,
				value: x.value,
				flag: x.flag,
				comment: x.comment
			}
		});
	}

	export default {
		components: {
			ViewData
		},
		props: {
			client: Object,
			dfn: String,
			date_begin: Date,
			date_end: Date
		},
		data() {
			return {
				patientinfo: null,
				resultset: null,
				calculate: true,
				calculations, reports
			};
		},
		computed: {
			params() {
				return { dfn: this.dfn, date_begin: strftime_vista(this.date_begin), date_end: strftime_vista(this.date_end) };
			},
			constants() {
				return this.patientinfo ? {
					DOB: { time: time_min, value: strptime_vista(this.patientinfo.dob) },
					Sex: { time: time_min, value: this.patientinfo.sex }
				} : {};
			},
			reports_selected() {
				return this.reports.filter(x => x.selected).map(x => x.value);
			}
		},
		watch: {
			async params(value, oldvalue) {
				this.patientinfo = await this.client.ORWPT16_ID_INFO(value.dfn);
				this.resultset = vitals_normalize(await this.client.GMV_EXTRACT_REC(value.dfn, value.date_end, value.date_begin)).concat(labs_normalize(await this.client.ORWLRR_INTERIM_RESULTS(value.dfn, value.date_end, value.date_begin)));
			}
		}
	};
</script>
