import { __assign, __awaiter, __generator, __spreadArray } from "tslib";
import dayjs from 'dayjs';
import equal from 'fast-deep-equal';
import { Component, triggerEvent, getValueFromProps } from '../_util/simply';
import { defaultLocaleText, CalendarDefaultProps, } from './props';
import { getMonthListFromRange, getSelectionModeFromValue, renderCells, getScrollIntoViewId, } from './utils';
import mixinValue from '../mixins/value';
import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect';
Component(CalendarDefaultProps, {
    getInstance: function () {
        if (this.$id) {
            return my;
        }
        return this;
    },
    getBoundingClientRect: function (query) {
        return __awaiter(this, void 0, void 0, function () {
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0: return [4 /*yield*/, getInstanceBoundingClientRect(this.getInstance(), query)];
                    case 1: return [2 /*return*/, _a.sent()];
                }
            });
        });
    },
    scrollIntoView: function (value) {
        this.updateScrollIntoViewId(getScrollIntoViewId(value));
    },
    clickCell: function (e) {
        var _a, _b;
        var time = e.currentTarget.dataset.time;
        var clickDate = dayjs(time.time);
        if (time.disabled) {
            return;
        }
        var value = this.getValue();
        var selectionModeFromValue = getSelectionModeFromValue(value);
        var selectionMode = (_b = (_a = getValueFromProps(this, 'selectionMode')) !== null && _a !== void 0 ? _a : selectionModeFromValue) !== null && _b !== void 0 ? _b : 'range';
        if (selectionMode === 'range') {
            if (Array.isArray(value)) {
                if (value.length === 1) {
                    var current = value[0];
                    if (dayjs(clickDate.toDate().getTime()).isBefore(dayjs(current))) {
                        this.updateValue([clickDate.toDate().getTime()]);
                    }
                    else {
                        this.updateValue([value[0], clickDate.toDate().getTime()]);
                    }
                }
                else {
                    this.updateValue([clickDate.toDate().getTime()]);
                }
            }
            else {
                this.updateValue([clickDate.toDate().getTime()]);
            }
        }
        else if (selectionMode === 'single') {
            this.updateValue(clickDate.toDate().getTime());
        }
    },
    setCurrentMonth: function (e) {
        this.setData({ headerState: e.month });
    },
    measurement: function () {
        var elementSize = this.data.elementSize;
        // 组件如果内嵌在 slot 里, 一定会被渲染出来, 但是此时 cellHight 为 0
        // 此时需要重新计算
        if (!elementSize || elementSize.cellHight === 0) {
            this.measurementFn();
        }
    },
    measurementFn: function () {
        var _this = this;
        Promise.all([
            this.getBoundingClientRect('.ant-calendar-body-container'),
            this.getBoundingClientRect('.ant-calendar-cells'),
            this.getBoundingClientRect('.ant-calendar-title-container'),
        ])
            .then(function (_a) {
            var bodyContainer = _a[0], cellContainer = _a[1], Title = _a[2];
            // 滚动的时候 top 和 bottom 等尺寸会变
            // 所以只能依赖 height 来计算
            var paddingHeight = bodyContainer.height - cellContainer.height - Title.height;
            var monthTitleHeight = Title.height + paddingHeight;
            var cellHight = cellContainer.height / (_this.data.monthList[0].cells.length / 7);
            _this.setData({
                elementSize: {
                    monthTitleHeight: monthTitleHeight,
                    cellHight: cellHight,
                    paddingHeight: paddingHeight,
                },
            });
        })
            .catch(function () {
            _this.setData({ elementSize: null });
        });
    },
    // scroll 触发滚动之后需要重置 scrollIntoViewId
    updateScrollIntoViewId: function (id) {
        var _this = this;
        this.setData({ scrollIntoViewId: id });
        var timer = setTimeout(function () {
            _this.setData({ scrollIntoViewId: '' });
            clearTimeout(timer);
        });
    },
    updateValue: function (newValue) {
        triggerEvent(this, 'change', newValue);
        if (!this.isControlled()) {
            this.update(newValue);
        }
    },
    updateData: function () {
        var _a = getValueFromProps(this, [
            'monthRange',
            'localeText',
            'weekStartsOn',
            'onFormatter',
            'onMonthFormatter',
        ]), monthRange = _a[0], plocaleText = _a[1], pweekStartsOn = _a[2], onFormatter = _a[3], onMonthFormatter = _a[4];
        var localeText = Object.assign({}, defaultLocaleText, plocaleText);
        var markItems = __spreadArray([], localeText.weekdayNames, true);
        var weekStartsOn = pweekStartsOn;
        if (weekStartsOn === 'Sunday') {
            var item = markItems.pop();
            if (item)
                markItems.unshift(item);
        }
        var value = this.getValue();
        var start = dayjs(monthRange === null || monthRange === void 0 ? void 0 : monthRange[0]).startOf('d');
        var end = dayjs(monthRange === null || monthRange === void 0 ? void 0 : monthRange[1]).startOf('d');
        var monthRangeList = getMonthListFromRange(start, end);
        var monthList = monthRangeList.map(function (p) {
            var cells = renderCells(p, weekStartsOn, value, localeText, 
            // 如果monthRange传入异常，用内置的时间范围
            start.isAfter(end) || start.isSame(end)
                ? [monthRangeList[0], dayjs(monthRangeList[1]).endOf('month')]
                : [start, end]);
            if (onFormatter && typeof onFormatter === 'function') {
                cells = cells.map(function (o) {
                    var _a;
                    var time = o.time, top = o.top, bottom = o.bottom, disabled = o.disabled, isSelectedBegin = o.isSelectedBegin, isSelectedEnd = o.isSelectedEnd, isSelected = o.isSelected, className = o.className, isRange = o.isRange;
                    var newState = (_a = onFormatter({
                        time: time,
                        top: top ? __assign({}, top) : undefined,
                        bottom: bottom ? __assign({}, bottom) : undefined,
                        disabled: disabled,
                        isSelectedBegin: isSelectedBegin,
                        isSelectedEnd: isSelectedEnd,
                        isSelected: isSelected,
                        className: className,
                        isRange: isRange,
                    }, value)) !== null && _a !== void 0 ? _a : {};
                    var result = __assign({}, o);
                    if (typeof newState === 'object') {
                        // 只允许修改的字段字段
                        ['top', 'bottom', 'disabled', 'className'].forEach(function (key) {
                            if (key in newState) {
                                result[key] = newState[key];
                            }
                        });
                    }
                    return result;
                });
            }
            var month = {
                title: p.format(localeText.title),
                className: '',
                cells: cells,
            };
            if (onMonthFormatter && typeof onMonthFormatter === 'function') {
                month = __assign(__assign({}, month), onMonthFormatter(p));
            }
            return month;
        });
        this.setData({ markItems: markItems, monthList: monthList });
    },
}, {
    elementSize: null,
    markItems: [],
    monthList: [],
    headerState: 0,
    scrollIntoViewId: '',
}, [mixinValue()], {
    didMount: function () {
        this.updateData();
        this.measurementFn();
        // 初始化默认值时，滚动到选中位置
        var _a = getValueFromProps(this, [
            'value',
            'defaultValue',
        ]), value = _a[0], defaultValue = _a[1];
        if (this.isControlled()) {
            this.updateScrollIntoViewId(getScrollIntoViewId(value));
        }
        else {
            defaultValue &&
                this.updateScrollIntoViewId(getScrollIntoViewId(defaultValue));
        }
    },
    didUpdate: function (prevProps, prevData) {
        if (!this.isEqualValue(prevData)) {
            // 滚动到已选的位置
            var changedScrollIntoView = getValueFromProps(this, 'changedScrollIntoView');
            changedScrollIntoView &&
                this.updateScrollIntoViewId(getScrollIntoViewId(this.getValue()));
        }
        if (!equal(prevProps, this.props) || !this.isEqualValue(prevData)) {
            this.updateData();
        }
    },
});
