import { Template } from 'meteor/templating';
import { Session } from 'meteor/session';
import { Tracker } from 'meteor/tracker';
import { ReactiveVar } from 'meteor/reactive-var';
import { _ } from 'meteor/underscore';
import { moment } from 'meteor/momentjs:moment';
import { OHIF } from 'meteor/ohif:core';
import { cornerstone } from 'meteor/ohif:cornerstone';

// Use Aldeed's meteor-template-extension package to replace the
// default viewportOverlay template.
// See https://github.com/aldeed/meteor-template-extension
const defaultTemplate = 'viewportOverlay';
Template.longitudinalViewportOverlay.replaces(defaultTemplate);

Template[defaultTemplate].onCreated(() => {
    const instance = Template.instance();
    instance.instanceMetadata = new ReactiveVar();

    const { DICOMTagDescriptions } = OHIF.viewerbase;
    instance.getValueByTagKeyword = tagKeyword => {
        const instanceMetadata = instance.instanceMetadata.get();
        const tagObject = DICOMTagDescriptions.find(tagKeyword);
        if (!instanceMetadata || !tagObject) return;
        return instanceMetadata.getRawValue(tagObject.tag);
    };
});

Template[defaultTemplate].onRendered(() => {
    const instance = Template.instance();
    const { studyInstanceUid, seriesInstanceUid } = instance.data;

    Tracker.autorun(computation => {
        Session.get('CornerstoneNewImage' + instance.data.viewportIndex);
        if (computation.firstRun) return;
        computation.stop();
        const imageIndex = instance.getImageIndex();
        OHIF.studies.loadStudy(studyInstanceUid).then(studyMetadata => {
            const seriesMetadata = studyMetadata.getSeriesByUID(seriesInstanceUid);
            const instanceMetadata = seriesMetadata.getInstanceByIndex(imageIndex);
            if (!instanceMetadata) return;
            instance.instanceMetadata.set(instanceMetadata);
        });
    });
});

// Add the TimepointName helper to the default template. The
// HTML of this template is replaced with that of longitudinalViewportOverlay
Template[defaultTemplate].helpers({
    studyInfo(tagKeyword) {
        const instance = Template.instance();
        instance.instanceMetadata.dep.depend();
        return instance.getValueByTagKeyword(tagKeyword);
    },

    getGenderAndAge() {
        const instance = Template.instance();
        const values = [];
        values.push(instance.getValueByTagKeyword('PatientSex'));

        const patientAge = instance.getValueByTagKeyword('PatientAge');
        const patientBirthDate = instance.getValueByTagKeyword('PatientBirthDate');
        if (patientAge) {
            values.push(patientAge);
        } else if (patientBirthDate) {
            const date = moment(patientBirthDate, 'YYYYMMDD');
            const yearDiff = moment().diff(date, 'years');
            if (yearDiff) {
                values.push((yearDiff + 'Y').padStart(4, '0'));
            } else {
                const monthDiff = moment().diff(date, 'months');
                if (monthDiff) {
                    values.push((monthDiff + 'M').padStart(4, '0'));
                } else {
                    const dayDiff = moment().diff(date, 'days') || 0;
                    values.push((dayDiff + 'D').padStart(4, '0'));
                }
            }
        }

        return values.filter(value => !!value).join(', ');
    },

    thickness() {
        const instance = Template.instance();
        Session.get('CornerstoneNewImage' + instance.data.viewportIndex);

        return instance.getValueByTagKeyword('SliceThickness');
    },

    location() {
        const instance = Template.instance();
        Session.get('CornerstoneNewImage' + instance.data.viewportIndex);

        const sliceLocation = instance.getValueByTagKeyword('SliceLocation');
        const tablePosition = instance.getValueByTagKeyword('TablePosition');
        const imagePositionPatient = instance.getValueByTagKeyword('ImagePositionPatient');
        return sliceLocation || tablePosition || imagePositionPatient;
    },

    spacingBetweenSlices() {
        const instance = Template.instance();
        Session.get('CornerstoneNewImage' + instance.data.viewportIndex);

        // TODO: Otherwise, displays a value derived from successive values
        // of Image Position (Patient) (0020,0032) perpendicular to
        // the Image Orientation (Patient) (0020,0037)

        return instance.getValueByTagKeyword('SpacingBetweenSlices');
    },

    zoom() {
        const instance = Template.instance();
        const { viewportIndex } = instance.data;
        const { getElementIfNotEmpty } = OHIF.viewerbase;
        Session.get('CornerstoneImageRendered' + viewportIndex);

        const element = getElementIfNotEmpty(viewportIndex);
        if (!element) return;

        const viewport = cornerstone.getViewport(element);
        if (!viewport) return;

        return viewport.scale;
    },

    wwwc() {
        const instance = Template.instance();
        const { viewportIndex } = instance.data;
        const { getElementIfNotEmpty, wlPresets } = OHIF.viewerbase;
        Session.get('CornerstoneImageRendered' + viewportIndex);
        wlPresets.changeObserver.depend();

        const element = getElementIfNotEmpty(viewportIndex);
        if (!element) return;

        const viewport = cornerstone.getViewport(element);
        if (!viewport) return;

        const ww = viewport.voi.windowWidth.toFixed(0);
        const wc = viewport.voi.windowCenter.toFixed(0);
        const result = [`W: ${ww}, L: ${wc}`];

        // Check if there's a preset with this W/L
        const preset = _.findWhere(OHIF.viewer.wlPresets, {
            ww: parseInt(ww),
            wc: parseInt(wc)
        });

        // Append the preset name to the result if found
        if (preset) {
            result .push(`(${preset.id})`);
        }

        return result.join(' ');
    },

    timepointName() {
        const instance = Template.instance();
        const studyInstanceUid = instance.data.studyInstanceUid;

        const timepointApi = OHIF.viewer.timepointApi;
        if (!timepointApi) return;

        const timepoints = timepointApi.study(studyInstanceUid);
        if (!timepoints || !timepoints.length) {
            return;
        }

        const timepoint = timepoints[0];

        return timepointApi.name(timepoint);
    },

    linked() {
        const linkedViewports = Session.get('StackImagePositionOffsetSynchronizerLinkedViewports') || [];
        return (linkedViewports.indexOf(this.viewportIndex) !== -1);
    }
});
