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

class Controller extends Section {
    constructor($element, $, vnWeekDays) {
        super($element, $);
        this.vnWeekDays = vnWeekDays;
        this.editMode = 'include';
    }

    $onInit() {
        this.refresh();
    }

    get path() {
        return `Zones/${this.$params.id}/events`;
    }

    get exclusionsPath() {
        return `Zones/${this.$params.id}/exclusions`;
    }

    get checked() {
        const geos = this.$.model.data || [];
        const checkedLines = [];
        for (let geo of geos) {
            if (geo.checked)
                checkedLines.push(geo);
        }
        return checkedLines;
    }

    refresh() {
        this.$.data = null;
        this.$.$applyAsync(() => {
            const params = {
                zoneFk: this.$params.id,
                started: this.$.calendar.firstDay,
                ended: this.$.calendar.lastDay
            };

            this.$http.get(`Zones/getEventsFiltered`, {params}).then(res => {
                const data = res.data;
                this.$.data = data;
            });
        });
    }

    formatWdays(weekDays) {
        if (!weekDays) return;

        let abrWdays = weekDays
            .split(',')
            .map(wday => this.vnWeekDays.map[wday].localeAbr);

        return abrWdays.length < 7
            ? abrWdays.join(', ')
            : this.$t('Everyday');
    }

    onSelection(days, type, weekday, events, exclusions, exclusionGeos) {
        if (this.editMode == 'include') {
            if (events.length)
                return this.editInclusion(events[0]);
            return this.createInclusion(type, days, weekday);
        } else if (this.editMode == 'exclude') {
            if (exclusions.length || exclusionGeos.length)
                return this.editExclusion(exclusions[0] || {}, exclusionGeos);
            return this.createExclusion(days);
        }
    }

    editExclusion(exclusion, exclusionGeos) {
        this.isNew = false;
        this.excludeSelected = angular.copy(exclusion);
        this.excludeSelected.type = exclusionGeos.length ?
            'specificLocations' : 'all';

        this.exclusionGeos = new Set();
        if (exclusionGeos.length) {
            this.excludeSelected.id = exclusionGeos[0].zoneExclusionFk;
            exclusionGeos.forEach(x => this.exclusionGeos.add(x.geoFk));
        }

        this.$.excludeDialog.show();
    }

    createExclusion(days) {
        this.isNew = true;
        this.excludeSelected = {
            type: 'all',
            dated: days[0]
        };
        this.exclusionGeos = new Set();
        this.$.excludeDialog.show();
    }

    onEditClick(row, event) {
        if (event.defaultPrevented) return;
        this.editInclusion(row);
    }

    editInclusion(row) {
        this.isNew = false;
        this.selected = angular.copy(row);
        this.selected.wdays = this.vnWeekDays.fromSet(row.weekDays);
        this.$.includeDialog.show();
    }

    createInclusion(type, days, weekday) {
        this.isNew = true;

        if (type == 'weekday') {
            let wdays = [];
            if (weekday) wdays[weekday] = true;

            this.selected = {
                type: 'indefinitely',
                wdays
            };
        } else {
            this.selected = {
                type: 'day',
                dated: days[0]
            };
        }

        this.$.includeDialog.show();
    }

    onIncludeResponse(response) {
        switch (response) {
        case 'accept': {
            let selected = this.selected;
            let type = selected.type;

            selected.weekDays = this.vnWeekDays.toSet(selected.wdays);

            if (type == 'day')
                selected.weekDays = '';
            else
                selected.dated = null;

            if (type != 'range') {
                selected.started = null;
                selected.ended = null;
            }

            let req;

            if (this.isNew)
                req = this.$http.post(this.path, selected);
            else
                req = this.$http.put(`${this.path}/${selected.id}`, selected);

            return req.then(() => {
                this.selected = null;
                this.isNew = null;
                this.refresh();
            });
        }
        case 'delete':
            return this.onDelete(this.selected.id)
                .then(response => response == 'accept');
        }
    }

    onExcludeResponse(response) {
        const type = this.excludeSelected.type;
        switch (response) {
        case 'accept': {
            if (type == 'all')
                return this.exclusionCreate();
            return this.exclusionGeoCreate();
        }
        case 'delete':
            return this.exclusionDelete(this.excludeSelected);
        }
    }

    onDeleteClick(id, event) {
        if (event.defaultPrevented) return;
        event.preventDefault();
        this.onDelete(id);
    }

    onDelete(id) {
        return this.$.confirm.show(
            response => this.onDeleteResponse(response, id));
    }

    onDeleteResponse(response, id) {
        if (response != 'accept' || !id) return;
        return this.$http.delete(`${this.path}/${id}`)
            .then(() => this.refresh());
    }

    exclusionCreate() {
        const excludeSelected = this.excludeSelected;
        const dated = excludeSelected.dated;
        let req;

        if (this.isNew)
            req = this.$http.post(this.exclusionsPath, [{dated}]);
        if (!this.isNew)
            req = this.$http.put(`${this.exclusionsPath}/${excludeSelected.id}`, {dated});

        return req.then(() => {
            this.refresh();
        });
    }

    exclusionGeoCreate() {
        const excludeSelected = this.excludeSelected;
        let req;
        const geoIds = [];
        this.exclusionGeos.forEach(id => geoIds.push(id));

        if (this.isNew) {
            const params = {
                zoneFk: parseInt(this.$params.id),
                date: excludeSelected.dated,
                geoIds
            };
            req = this.$http.post(`Zones/exclusionGeo`, params);
        } else {
            const params = {
                zoneExclusionFk: this.excludeSelected.id,
                geoIds
            };
            req = this.$http.post(`Zones/updateExclusionGeo`, params);
        }
        return req.then(() => this.refresh());
    }

    exclusionDelete(exclusion) {
        const path = `${this.exclusionsPath}/${exclusion.id}`;
        return this.$http.delete(path)
            .then(() => this.refresh());
    }

    set excludeSearch(value) {
        this._excludeSearch = value;
        if (!value) this.onSearch();
    }

    get excludeSearch() {
        return this._excludeSearch;
    }

    onKeyDown(event) {
        if (event.key == 'Enter') {
            event.preventDefault();
            this.onSearch();
        }
    }

    onSearch() {
        const params = {search: this._excludeSearch};
        if (this.excludeSelected.type == 'specificLocations') {
            this.$.model.applyFilter({}, params).then(() => {
                const data = this.$.model.data;
                this.getChecked(data);
                this.$.treeview.data = data;
            });
        }
    }

    onFetch(item) {
        const params = item ? {parentId: item.id} : null;
        return this.$.model.applyFilter({}, params).then(() => {
            const data = this.$.model.data;
            this.getChecked(data);
            return data;
        });
    }

    onSort(a, b) {
        if (b.selected !== a.selected) {
            if (a.selected == null)
                return 1;
            if (b.selected == null)
                return -1;
            return b.selected - a.selected;
        }

        return a.name.localeCompare(b.name);
    }

    getChecked(data) {
        for (let geo of data) {
            geo.checked = this.exclusionGeos.has(geo.id);
            if (geo.childs) this.getChecked(geo.childs);
        }
    }

    onItemCheck(geoId, checked) {
        if (checked)
            this.exclusionGeos.add(geoId);
        else
            this.exclusionGeos.delete(geoId);
    }
}
Controller.$inject = ['$element', '$scope', 'vnWeekDays'];

ngModule.vnComponent('vnZoneEvents', {
    template: require('./index.html'),
    controller: Controller,
    bindings: {
        zone: '<'
    },
    require: {
        card: '^vnZoneCard'
    }
});