import { getDateRect, isSameDate, getMonthDateRect, isValidDate, getDate } from '../date';
export default class TCalendar {
    constructor(options = {}) {
        this.type = 'single';
        Object.assign(this, options);
        if (!this.minDate)
            this.minDate = getDate();
        if (!this.maxDate)
            this.maxDate = getDate(6);
    }
    getTrimValue() {
        const { value, type } = this;
        const format = (val) => {
            if (val instanceof Date)
                return val;
            if (typeof val === 'number')
                return new Date(val);
            return new Date();
        };
        if (type === 'single' && isValidDate(value))
            return format(value);
        if (type === 'multiple' || type === 'range') {
            if (Array.isArray(value)) {
                const isValid = value.every((item) => isValidDate(item));
                return isValid ? value.map((item) => format(item)) : [];
            }
            return [];
        }
    }
    getDays(weekdays) {
        const ans = [];
        let i = this.firstDayOfWeek % 7;
        while (ans.length < 7) {
            ans.push(weekdays[i]);
            i = (i + 1) % 7;
        }
        return ans;
    }
    getMonths() {
        const ans = [];
        const selectedDate = this.getTrimValue();
        const { minDate, maxDate, type, format } = this;
        let { year: minYear, month: minMonth, time: minTime } = getDateRect(minDate);
        const { year: maxYear, month: maxMonth, time: maxTime } = getDateRect(maxDate);
        const calcType = (year, month, date) => {
            const curDate = new Date(year, month, date, 23, 59, 59);
            if (type === 'single' && selectedDate) {
                if (isSameDate({ year, month, date }, selectedDate))
                    return 'selected';
            }
            if (type === 'multiple' && selectedDate) {
                const hit = selectedDate.some((item) => isSameDate({ year, month, date }, item));
                if (hit) {
                    return 'selected';
                }
            }
            if (type === 'range' && selectedDate) {
                if (Array.isArray(selectedDate)) {
                    const [startDate, endDate] = selectedDate;
                    if (startDate && isSameDate({ year, month, date }, startDate))
                        return 'start';
                    if (endDate && isSameDate({ year, month, date }, endDate))
                        return 'end';
                    if (startDate && endDate && curDate.getTime() > startDate.getTime() && curDate.getTime() < endDate.getTime())
                        return 'centre';
                }
            }
            const minCurDate = new Date(year, month, date, 0, 0, 0);
            if (curDate.getTime() < minTime || minCurDate.getTime() > maxTime) {
                return 'disabled';
            }
            return '';
        };
        while (minYear < maxYear || (minYear === maxYear && minMonth <= maxMonth)) {
            const target = getMonthDateRect(new Date(minYear, minMonth, 1));
            const months = [];
            for (let i = 1; i <= 31; i++) {
                if (i > target.lastDate)
                    break;
                const dateObj = {
                    date: new Date(minYear, minMonth, i),
                    day: i,
                    type: calcType(minYear, minMonth, i),
                };
                months.push(format ? format(dateObj) : dateObj);
            }
            ans.push({
                year: minYear,
                month: minMonth,
                months,
                weekdayOfFirstDay: target.weekdayOfFirstDay,
            });
            const curDate = getDateRect(new Date(minYear, minMonth + 1, 1));
            minYear = curDate.year;
            minMonth = curDate.month;
        }
        return ans;
    }
    select({ cellType, year, month, date }) {
        const { type } = this;
        const selectedDate = this.getTrimValue();
        if (cellType === 'disabled')
            return;
        const selected = new Date(year, month, date);
        this.value = selected;
        if (type === 'range' && Array.isArray(selectedDate)) {
            if (selectedDate.length === 1 && selected > selectedDate[0]) {
                this.value = [selectedDate[0], selected];
            }
            else {
                this.value = [selected];
            }
        }
        else if (type === 'multiple' && Array.isArray(selectedDate)) {
            const newVal = [...selectedDate];
            const index = selectedDate.findIndex((item) => isSameDate(item, selected));
            if (index > -1) {
                newVal.splice(index, 1);
            }
            else {
                newVal.push(selected);
            }
            this.value = newVal;
        }
        return this.value;
    }
}
