import ngModule from '../module';
import Section from 'salix/components/section';
import './style.scss';

class Controller extends Section {
    constructor($element, $) {
        super($element, $);
        this.date = new Date();
        this.events = {};
        this.buildYearFilter();
    }

    get year() {
        return this.date.getFullYear();
    }

    set year(value) {
        const newYear = new Date();
        newYear.setFullYear(value);

        this.date = newYear;

        this.refresh().then(() => this.repaint());
    }

    get date() {
        return this._date;
    }

    set date(value) {
        this._date = value;
        value.setHours(0, 0, 0, 0);

        const started = new Date(value.getTime());
        started.setMonth(0);
        started.setDate(1);
        this.started = started;

        const ended = new Date(value.getTime());
        ended.setMonth(12);
        ended.setDate(0);
        this.ended = ended;

        this.months = new Array(12);

        for (let i = 0; i < this.months.length; i++) {
            const now = new Date(value.getTime());
            now.setDate(1);
            now.setMonth(i);
            this.months[i] = now;
        }
    }

    get worker() {
        return this._worker;
    }

    set worker(value) {
        this._worker = value;

        if (value) {
            this.refresh().then(() => this.repaint());
            this.getIsSubordinate();
        }
    }

    buildYearFilter() {
        const currentYear = new Date().getFullYear();
        const minRange = currentYear - 5;

        const years = [];
        for (let i = currentYear; i > minRange; i--)
            years.push({year: i});

        this.yearFilter = years;
    }

    getIsSubordinate() {
        this.$http.get(`Workers/${this.worker.id}/isSubordinate`).then(res =>
            this.isSubordinate = res.data
        );
    }

    onData(data) {
        this.events = {};
        this.calendar = data.calendar;

        let addEvent = (day, newEvent) => {
            const timestamp = new Date(day).getTime();
            const event = this.events[timestamp];

            if (event) {
                const oldName = event.name;
                Object.assign(event, newEvent);
                event.name = `${oldName}, ${event.name}`;
            } else
                this.events[timestamp] = newEvent;
        };

        if (data.holidays) {
            data.holidays.forEach(holiday => {
                const holidayDetail = holiday.detail && holiday.detail.name;
                const holidayType = holiday.type && holiday.type.name;
                const holidayName = holidayDetail || holidayType;

                addEvent(holiday.dated, {
                    name: holidayName,
                    className: 'festive'
                });
            });
        }
        if (data.absences) {
            data.absences.forEach(absence => {
                let type = absence.absenceType;
                addEvent(absence.dated, {
                    name: type.name,
                    color: type.rgb,
                    type: type.code,
                    absenceId: absence.id
                });
            });
        }
    }

    repaint() {
        let calendars = this.element.querySelectorAll('vn-calendar');
        for (let calendar of calendars)
            calendar.$ctrl.repaint();
    }

    formatDay(day, element) {
        let event = this.events[day.getTime()];
        if (!event) return;

        let dayNumber = element.firstElementChild;
        dayNumber.title = event.name;
        dayNumber.style.backgroundColor = event.color;

        if (event.border)
            dayNumber.style.border = event.border;

        if (event.className)
            dayNumber.classList.add(event.className);
    }

    pick(absenceType) {
        if (!this.isSubordinate) return;
        if (absenceType == this.absenceType)
            absenceType = null;

        this.absenceType = absenceType;
    }

    onSelection($event, $days) {
        if (!this.absenceType)
            return this.vnApp.showMessage(this.$t('Choose an absence type from the right menu'));

        if (this.year != new Date().getFullYear())
            return this.vnApp.showMessage(this.$t('You can just add absences within the current year'));

        const day = $days[0];
        const stamp = day.getTime();
        const event = this.events[stamp];
        const calendar = $event.target.closest('vn-calendar').$ctrl;

        if (event) {
            if (event.type == this.absenceType.code)
                this.delete(calendar, day, event);
            else
                this.edit(calendar, event);
        } else
            this.create(calendar, day);
    }

    create(calendar, dated) {
        const absenceType = this.absenceType;
        const params = {
            dated: dated,
            absenceTypeId: absenceType.id
        };

        const path = `Workers/${this.$params.id}/createAbsence`;
        this.$http.post(path, params).then(res => {
            const newEvent = res.data;
            this.events[dated.getTime()] = {
                name: absenceType.name,
                color: absenceType.rgb,
                type: absenceType.code,
                absenceId: newEvent.id
            };

            this.repaintCanceller(() =>
                this.refresh().then(calendar.repaint())
            );
        });
    }

    edit(calendar, event) {
        const absenceType = this.absenceType;
        const params = {
            absenceId: event.absenceId,
            absenceTypeId: absenceType.id
        };
        const path = `Workers/${this.$params.id}/updateAbsence`;
        this.$http.patch(path, params).then(() => {
            event.color = absenceType.rgb;
            event.name = absenceType.name;
            event.type = absenceType.code;

            this.repaintCanceller(() =>
                this.refresh().then(calendar.repaint())
            );
        });
    }

    delete(calendar, day, event) {
        const params = {absenceId: event.absenceId};
        const path = `Workers/${this.$params.id}/deleteAbsence`;
        this.$http.delete(path, {params}).then(() => {
            delete this.events[day.getTime()];

            this.repaintCanceller(() =>
                this.refresh().then(calendar.repaint())
            );
        });
    }

    repaintCanceller(cb) {
        if (this.canceller) {
            clearTimeout(this.canceller);
            this.canceller = null;
        }

        this.canceller = setTimeout(
            () => cb(), 500);
    }

    refresh() {
        const params = {
            workerFk: this.worker.id,
            started: this.started,
            ended: this.ended
        };
        return this.$http.get(`Calendars/absences`, {params})
            .then(res => this.onData(res.data));
    }
}

ngModule.vnComponent('vnWorkerCalendar', {
    template: require('./index.html'),
    controller: Controller,
    bindings: {
        worker: '<'
    }
});