import ngModule from '../module';
import Component from 'core/lib/component';
import './style.scss';

class Controller extends Component {
    constructor($element, $) {
        super($element, $);
        this.nMonths = 4;

        let date = new Date();
        date.setDate(1);
        date.setHours(0, 0, 0, 0);
        this.date = date;
    }

    get date() {
        return this._date;
    }

    set date(value) {
        this._date = value;
        let stamp = value.getTime();

        let firstDay = new Date(stamp);
        firstDay.setDate(1);
        this.firstDay = firstDay;

        let lastDay = new Date(stamp);
        lastDay.setMonth(lastDay.getMonth() + this.nMonths);
        lastDay.setDate(0);
        this.lastDay = lastDay;

        this.months = [];
        for (let i = 0; i < this.nMonths; i++) {
            let monthDate = new Date(stamp);
            monthDate.setMonth(value.getMonth() + i);
            this.months.push(monthDate);
        }

        this.refreshEvents();
    }

    step(direction) {
        let date = new Date(this.date.getTime());
        date.setMonth(date.getMonth() + (this.nMonths * direction));
        this.date = date;
    }

    get data() {
        return this._data;
    }

    set data(value) {
        this._data = value;

        value = value || {};
        this.events = value.events;
        this.exclusions = value.exclusions;

        if (this.events) {
            let codes = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
            for (event of this.events) {
                if (!event.weekDays) continue;
                let weekDays = event.weekDays.split(',');
                event.wdays = [];
                for (let wday of weekDays) {
                    let index = codes.indexOf(wday);
                    if (index !== -1) event.wdays[index] = true;
                }
            }
        }

        this.refreshEvents();

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

    refreshEvents() {
        function getDate(date) {
            return date && new Date(date).setHours(0, 0, 0, 0);
        }

        let exclusionsMap = {};
        if (this.exclusions) {
            for (let exclusion of this.exclusions)
                exclusionsMap[getDate(exclusion.day)] = exclusion;
        }

        this.days = {};
        let day = new Date(this.firstDay.getTime());

        while (day < this.lastDay) {
            let stamp = day.getTime();
            let wday = day.getDay();
            let dayEvents = [];

            if (this.events) {
                for (let event of this.events) {
                    let match;
                    let from = getDate(event.from);
                    let to = getDate(event.to);

                    if (event.from && event.to) {
                        match = stamp >= from && stamp <= to
                            && event.wdays[wday];
                    } else if (event.from)
                        match = from == stamp;
                    else
                        match = event.wdays[wday];

                    if (match)
                        dayEvents.push(event);
                }
            }

            let exclusion = exclusionsMap[stamp];

            if (dayEvents.length || exclusion) {
                let dayData = {};
                if (dayEvents.length) dayData.events = dayEvents;
                if (exclusion) dayData.exclusion = exclusion;
                this.days[stamp] = dayData;
            }

            day.setDate(day.getDate() + 1);
        }
    }

    onSelection($days, $type, $weekday) {
        let $data = [];
        for (let day of $days) {
            let dayData = this.days[day.getTime()];
            if (dayData) $data.push(dayData);
        }

        this.emit('selection', {
            $days,
            $type,
            $weekday,
            $data
        });
    }

    hasEvents(day) {
        return this.days[day.getTime()] != null;
    }

    getClass(day) {
        let dayData = this.days[day.getTime()];
        return dayData && dayData.exclusion ? 'excluded' : '';
    }
}

ngModule.component('vnZoneCalendar', {
    template: require('./index.html'),
    controller: Controller,
    bindings: {
        data: '<?'
    }
});