/**
 * amis-ui v6.11.0-beta.8
 * Copyright 2018-2025 fex
 */

import { __extends, __assign, __values } from 'tslib';
import moment from 'moment';
import React__default from 'react';
import merge from 'lodash/merge';
import { isObject, getRange, localeable } from 'amis-core';
import { Icon } from '../icons.js';
import Picker from '../Picker.js';
import Downshift from 'downshift';

var CustomTimeView = /** @class */ (function (_super) {
    __extends(CustomTimeView, _super);
    function CustomTimeView(props) {
        var _this = _super.call(this, props) || this;
        _this.padValues = {
            hours: 2,
            minutes: 2,
            seconds: 2,
            milliseconds: 3
        };
        _this.timeConstraints = {
            hours: {
                min: 0,
                max: 23,
                step: 1
            },
            minutes: {
                min: 0,
                max: 59,
                step: 1
            },
            seconds: {
                min: 0,
                max: 59,
                step: 1
            },
            milliseconds: {
                min: 0,
                max: 999,
                step: 1
            }
        };
        /** 基于 timeConstraints 计算出的时间列表 */
        _this.timeList = [];
        _this.shoudExtractTimeConstraintsList = function () {
            var timeConstraints = _this.timeConstraints;
            var result = false;
            if (!timeConstraints || !isObject(timeConstraints)) {
                return result;
            }
            ['hours', 'minutes', 'seconds'].forEach(function (timeScale) {
                var _a = timeConstraints[timeScale], min = _a.min, max = _a.max, step = _a.step;
                if (result !== false) {
                    return;
                }
                if (timeScale === 'hours') {
                    result = min > 0 || max < 23 || step > 1;
                }
                else if (timeScale === 'minutes') {
                    result = min > 0 || max < 59 || step > 1;
                }
                else if (timeScale === 'seconds') {
                    result = min > 0 || max < 59 || step > 1;
                }
            });
            return result;
        };
        _this.updateSelectedDate = function (event) {
            // need confirm
            if (_this.props.requiredConfirm) {
                var viewDate = _this.props.viewDate.clone();
                var currentDate = _this.props.selectedDate || viewDate;
                var target = event.target;
                var modifier = 0;
                if (~target.className.indexOf('rdtNew')) {
                    modifier = 1;
                }
                if (~target.className.indexOf('rdtOld')) {
                    modifier = -1;
                }
                viewDate
                    .month(viewDate.month() + modifier)
                    .date(parseInt(target.getAttribute('data-value'), 10))
                    .hours(currentDate.hours())
                    .minutes(currentDate.minutes())
                    .seconds(currentDate.seconds())
                    .milliseconds(currentDate.milliseconds());
                _this.props.setDateTimeState({
                    viewDate: viewDate,
                    selectedDate: viewDate.clone()
                });
                return;
            }
            _this.props.updateSelectedDate(event, true);
        };
        _this.renderDayPart = function () {
            var _a = _this.props, __ = _a.translate, cx = _a.classnames;
            return (React__default.createElement("div", { key: "dayPart", className: cx('CalendarCounter CalendarCounter--daypart') },
                React__default.createElement("span", { key: "up", className: cx('CalendarCounter-btn CalendarCounter-btn--up'), onClick: _this.onStartClicking('toggleDayPart', 'hours'), onContextMenu: _this.disableContextMenu },
                    React__default.createElement(Icon, { icon: "right-arrow-bold" })),
                React__default.createElement("div", { className: cx('CalendarCounter-value'), key: _this.state.daypart }, __(_this.state.daypart)),
                React__default.createElement("span", { key: "down", className: cx('CalendarCounter-btn CalendarCounter-btn--down'), onClick: _this.onStartClicking('toggleDayPart', 'hours'), onContextMenu: _this.disableContextMenu },
                    React__default.createElement(Icon, { icon: "right-arrow-bold" }))));
        };
        _this.getCounterValue = function (type) {
            if (type !== 'daypart') {
                var value = _this.state[type];
                if (type === 'hours' &&
                    _this.props.timeFormat.toLowerCase().indexOf(' a') !== -1) {
                    value = ((value - 1) % 12) + 1;
                    if (value === 0) {
                        value = 12;
                    }
                }
                return parseInt(value);
            }
            return 0;
        };
        _this.renderCounter = function (type) {
            var cx = _this.props.classnames;
            if (type !== 'daypart') {
                var value = _this.getCounterValue(type);
                var _a = _this.timeConstraints[type], min_1 = _a.min, max_1 = _a.max, step = _a.step;
                return (React__default.createElement("div", { key: type, className: cx('CalendarCounter') },
                    React__default.createElement("span", { key: "up", className: cx('CalendarCounter-btn CalendarCounter-btn--up'), onMouseDown: _this.onStartClicking('increase', type), onContextMenu: _this.disableContextMenu },
                        React__default.createElement(Icon, { icon: "right-arrow-bold" })),
                    React__default.createElement("div", { key: "c", className: cx('CalendarCounter-value') },
                        React__default.createElement("input", { type: "text", value: _this.pad(type, value), className: cx('CalendarInput'), min: min_1, max: max_1, step: step, onChange: function (e) {
                                return _this.props.setTime(type, Math.max(min_1, Math.min(parseInt(e.currentTarget.value.replace(/\D/g, ''), 10) ||
                                    0, max_1)));
                            } })),
                    React__default.createElement("span", { key: "do", className: cx('CalendarCounter-btn CalendarCounter-btn--down'), onMouseDown: _this.onStartClicking('decrease', type), onContextMenu: _this.disableContextMenu },
                        React__default.createElement(Icon, { icon: "right-arrow-bold" }))));
            }
            return null;
        };
        _this.onConfirm = function (value) {
            // 修正am、pm
            var hourIndex = _this.state.counters.indexOf('hours');
            if (hourIndex !== -1 &&
                _this.state.daypart !== false &&
                _this.props.timeFormat.toLowerCase().indexOf(' a') !== -1) {
                var amMode = value.splice(-1, 1)[0];
                var hour = value[hourIndex] % 12;
                // 修正pm
                amMode.toLowerCase().indexOf('p') !== -1 && (hour = hour + 12);
                value[hourIndex] = hour;
            }
            _this.props.onConfirm &&
                _this.props.onConfirm(value, _this.state.counters);
        };
        _this.getDayPartOptions = function () {
            var __ = _this.props.translate;
            var options = ['am', 'pm'];
            if (_this.props.timeFormat.indexOf(' A') !== -1) {
                options = ['AM', 'PM'];
            }
            return options.map(function (daypart) { return ({
                text: __(daypart),
                value: daypart
            }); });
        };
        _this.onPickerChange = function (value, index) {
            var time = {};
            _this.state.counters.forEach(function (type, i) { return (time[type] = value[i]); });
            if (_this.state.daypart !== false &&
                index > _this.state.counters.length - 1) {
                time.daypart = value[value.length - 1];
            }
            _this.setState(function (prevState) {
                return __assign(__assign({}, prevState), time);
            });
            // @ts-ignore
            _this.props.onChange && _this.props.onChange(value);
        };
        _this.renderTimeViewPicker = function () {
            var __ = _this.props.translate;
            var title = __('Date.titleTime');
            var columns = [];
            var values = [];
            _this.state.counters.forEach(function (type) {
                if (type !== 'daypart') {
                    var _a = _this.timeConstraints[type], min = _a.min, max = _a.max, step = _a.step;
                    // 修正am pm时hours可选最大值
                    if (type === 'hours' &&
                        _this.state.daypart !== false &&
                        _this.props.timeFormat.toLowerCase().indexOf(' a') !== -1) {
                        max = max > 12 ? 12 : max;
                    }
                    columns.push({
                        options: getRange(min, max, step).map(function (item) {
                            return {
                                text: _this.pad(type, item),
                                value: item
                            };
                        })
                    });
                    values.push(parseInt(_this.state[type], 10));
                }
            });
            if (_this.state.daypart !== false) {
                columns.push({
                    options: _this.getDayPartOptions()
                });
                values.push(_this.state.daypart);
            }
            return (React__default.createElement(Picker, { translate: _this.props.translate, locale: _this.props.locale, title: title, columns: columns, value: values, onConfirm: _this.onConfirm, onClose: _this.props.onClose, showToolbar: _this.props.showToolbar, onChange: _this.onPickerChange }));
        };
        _this.setTime = function (type, value) {
            var date = (_this.props.selectedDate || _this.props.viewDate).clone();
            date[type](value);
            _this.props.setDateTimeState({
                viewDate: date.clone(),
                selectedDate: date.clone()
            });
            if (!_this.props.requiredConfirm) {
                _this.props.onChange(date);
            }
        };
        _this.scrollToTop = function (type, value, i, label) {
            var _a, _b;
            var elf = document.getElementById("".concat(_this.state.uniqueTag, "-").concat(i, "-input"));
            var _c = _this.timeConstraints[type], min = _c.min, step = _c.step;
            var offset = (value - min) / step;
            var height = 28; /** 单个选项的高度 */
            (_b = (_a = elf === null || elf === void 0 ? void 0 : elf.parentNode) === null || _a === void 0 ? void 0 : _a.scrollTo) === null || _b === void 0 ? void 0 : _b.call(_a, {
                top: offset * height,
                behavior: label === 'init' ? 'auto' : 'smooth'
            });
        };
        /**
         * 选择当前时间，如果设置了timeConstraints，则选择最接近的时间
         */
        _this.selectNowTime = function () {
            var _a = _this.props, setDateTimeState = _a.setDateTimeState, timeFormat = _a.timeFormat;
            var useClosetDate = _this.shoudExtractTimeConstraintsList();
            if (useClosetDate) {
                var timeList = _this.timeList;
                var now_1 = moment().clone();
                var closetDate_1 = now_1.clone();
                var minDiff_1 = Infinity;
                /** 遍历时间列表，找出最接近此刻的时间 */
                timeList.forEach(function (item, index) {
                    var date = moment(item, timeFormat);
                    var diff = Math.abs(now_1.diff(date));
                    if (diff < minDiff_1) {
                        minDiff_1 = diff;
                        closetDate_1 = date;
                    }
                });
                setDateTimeState({ viewDate: closetDate_1, selectedDate: closetDate_1 }, function () {
                    return _this.confirm();
                });
            }
            else {
                setDateTimeState({ viewDate: moment().clone(), selectedDate: moment().clone() }, function () { return _this.confirm(); });
            }
        };
        _this.confirm = function () {
            var _a, _b;
            var date = (_this.props.selectedDate || _this.props.viewDate).clone();
            // 如果 minDate 是可用的，且比当前日期晚，则用 minDate
            if (((_a = _this.props.minDate) === null || _a === void 0 ? void 0 : _a.isValid()) && ((_b = _this.props.minDate) === null || _b === void 0 ? void 0 : _b.isAfter(date))) {
                date = _this.props.minDate.clone();
            }
            _this.props.setDateTimeState({
                selectedDate: date
            });
            _this.props.onChange(date);
            _this.props.onClose && _this.props.onClose();
        };
        _this.cancel = function () {
            _this.props.onClose && _this.props.onClose();
        };
        _this.state = __assign(__assign({}, _this.calculateState(_this.props)), { uniqueTag: new Date().valueOf() });
        if (_this.props.timeConstraints) {
            _this.timeConstraints = merge(_this.timeConstraints, _this.props.timeConstraints);
        }
        return _this;
    }
    CustomTimeView.prototype.componentDidMount = function () {
        var e_1, _a, e_2, _b, e_3, _c;
        var _this = this;
        var _d = this.props, timeFormat = _d.timeFormat, selectedDate = _d.selectedDate, viewDate = _d.viewDate, isEndDate = _d.isEndDate;
        var formatMap = {
            hours: 'HH',
            minutes: 'mm',
            seconds: 'ss'
        };
        var date = selectedDate || (isEndDate ? viewDate.endOf('day') : viewDate);
        timeFormat.split(':').forEach(function (format, i) {
            var type = /h/i.test(format)
                ? 'hours'
                : /m/.test(format)
                    ? 'minutes'
                    : /s/.test(format)
                        ? 'seconds'
                        : '';
            if (type) {
                _this.scrollToTop(type, parseInt(date.format(formatMap[type]), 10), i, 'init');
            }
        });
        /** 如果设置了step或者min、max限制，则计算出时间列表提供给后续使用 */
        if (this.shoudExtractTimeConstraintsList()) {
            var hours = this.computedTimeOptions('hours').map(function (item) { return item.value; });
            var minutes = timeFormat.split(':').some(function (f) { return /^(mm|m)$/.test(f); })
                ? this.computedTimeOptions('minutes').map(function (item) { return item.value; })
                : ['00'];
            var seconds = timeFormat.split(':').some(function (f) { return /^(ss|s)$/.test(f); })
                ? this.computedTimeOptions('seconds').map(function (item) { return item.value; })
                : ['00'];
            var result = [];
            try {
                for (var hours_1 = __values(hours), hours_1_1 = hours_1.next(); !hours_1_1.done; hours_1_1 = hours_1.next()) {
                    var h = hours_1_1.value;
                    try {
                        for (var minutes_1 = (e_2 = void 0, __values(minutes)), minutes_1_1 = minutes_1.next(); !minutes_1_1.done; minutes_1_1 = minutes_1.next()) {
                            var m = minutes_1_1.value;
                            try {
                                for (var seconds_1 = (e_3 = void 0, __values(seconds)), seconds_1_1 = seconds_1.next(); !seconds_1_1.done; seconds_1_1 = seconds_1.next()) {
                                    var s = seconds_1_1.value;
                                    result.push("".concat(h, ":").concat(m, ":").concat(s));
                                }
                            }
                            catch (e_3_1) { e_3 = { error: e_3_1 }; }
                            finally {
                                try {
                                    if (seconds_1_1 && !seconds_1_1.done && (_c = seconds_1.return)) _c.call(seconds_1);
                                }
                                finally { if (e_3) throw e_3.error; }
                            }
                        }
                    }
                    catch (e_2_1) { e_2 = { error: e_2_1 }; }
                    finally {
                        try {
                            if (minutes_1_1 && !minutes_1_1.done && (_b = minutes_1.return)) _b.call(minutes_1);
                        }
                        finally { if (e_2) throw e_2.error; }
                    }
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (hours_1_1 && !hours_1_1.done && (_a = hours_1.return)) _a.call(hours_1);
                }
                finally { if (e_1) throw e_1.error; }
            }
            this.timeList = result;
        }
    };
    CustomTimeView.prototype.componentDidUpdate = function (preProps) {
        if (preProps.viewDate !== this.props.viewDate ||
            preProps.selectedDate !== this.props.selectedDate ||
            preProps.timeFormat !== this.props.timeFormat) {
            this.setState(this.calculateState(this.props));
        }
    };
    CustomTimeView.prototype.onStartClicking = function (action, type) {
        var me = this;
        return function () {
            var update = {};
            update[type] = me[action](type);
            me.setState(update);
            me.timer = setTimeout(function () {
                me.increaseTimer = setInterval(function () {
                    update[type] = me[action](type);
                    me.setState(update);
                }, 70);
            }, 500);
            me.mouseUpListener = function () {
                clearTimeout(me.timer);
                clearInterval(me.increaseTimer);
                me.props.setTime(type, me.state[type]);
                document.body.removeEventListener('mouseup', me.mouseUpListener);
                document.body.removeEventListener('touchend', me.mouseUpListener);
            };
            document.body.addEventListener('mouseup', me.mouseUpListener);
            document.body.addEventListener('touchend', me.mouseUpListener);
        };
    };
    CustomTimeView.prototype.updateMilli = function (e) {
        var milli = parseInt(e.target.value, 10);
        if (milli === e.target.value && milli >= 0 && milli < 1000) {
            this.props.setTime('milliseconds', milli);
            this.setState({ milliseconds: milli });
        }
    };
    CustomTimeView.prototype.renderHeader = function () {
        if (!this.props.dateFormat)
            return null;
        var date = this.props.selectedDate || this.props.viewDate;
        return React__default.createElement('thead', { key: 'h' }, React__default.createElement('tr', {}, React__default.createElement('th', {
            className: 'rdtSwitch',
            colSpan: 4,
            onClick: this.props.showView('days')
        }, date.format(this.props.dateFormat))));
    };
    CustomTimeView.prototype.toggleDayPart = function (type) {
        // type is always 'hours'
        var value = parseInt(this.state[type], 10) + 12;
        if (value > this.timeConstraints[type].max)
            value =
                this.timeConstraints[type].min +
                    (value - (this.timeConstraints[type].max + 1));
        return this.pad(type, value);
    };
    CustomTimeView.prototype.increase = function (type) {
        var value = parseInt(this.state[type], 10) + this.timeConstraints[type].step;
        if (value > this.timeConstraints[type].max)
            value =
                this.timeConstraints[type].min +
                    (value - (this.timeConstraints[type].max + 1));
        if (value < this.timeConstraints[type].min) {
            value = this.timeConstraints[type].min;
        }
        return this.pad(type, value);
    };
    CustomTimeView.prototype.decrease = function (type) {
        var value = parseInt(this.state[type], 10) - this.timeConstraints[type].step;
        if (value < this.timeConstraints[type].min)
            value =
                this.timeConstraints[type].max +
                    1 -
                    (this.timeConstraints[type].min - value);
        return this.pad(type, value);
    };
    CustomTimeView.prototype.pad = function (type, value) {
        var str = value + '';
        while (str.length < this.padValues[type])
            str = '0' + str;
        return str;
    };
    CustomTimeView.prototype.disableContextMenu = function (event) {
        event.preventDefault();
        return false;
    };
    CustomTimeView.prototype.calculateState = function (props) {
        var date = props.selectedDate || props.viewDate, format = props.timeFormat, counters = [];
        if (format.toLowerCase().indexOf('h') !== -1) {
            counters.push('hours');
            if (format.indexOf('m') !== -1) {
                counters.push('minutes');
                if (format.indexOf('s') !== -1) {
                    counters.push('seconds');
                }
            }
        }
        var hours = parseInt(date.format('H'), 10);
        var daypart = false;
        if (this.state !== null &&
            this.props.timeFormat.toLowerCase().indexOf(' a') !== -1) {
            if (this.props.timeFormat.indexOf(' A') !== -1) {
                daypart = hours >= 12 ? 'PM' : 'AM';
            }
            else {
                daypart = hours >= 12 ? 'pm' : 'am';
            }
        }
        return {
            hours: hours,
            minutes: date.format('mm'),
            seconds: date.format('ss'),
            milliseconds: date.format('SSS'),
            daypart: daypart,
            counters: counters
        };
    };
    CustomTimeView.prototype.computedTimeOptions = function (timeScale) {
        var _a;
        var _b = (_a = this.timeConstraints) === null || _a === void 0 ? void 0 : _a[timeScale], min = _b.min, max = _b.max, step = _b.step;
        return Array.from({ length: max - min + 1 }, function (item, index) {
            var value = (index + min)
                .toString()
                .padStart(timeScale !== 'milliseconds' ? 2 : 3, '0');
            return index % step === 0 ? { label: value, value: value } : undefined;
        }).filter(function (item) { return !!item; });
    };
    CustomTimeView.prototype.render = function () {
        var _this = this;
        var _a = this.props, timeFormat = _a.timeFormat, selectedDate = _a.selectedDate, viewDate = _a.viewDate, isEndDate = _a.isEndDate, cx = _a.classnames, timeRangeHeader = _a.timeRangeHeader, mobileUI = _a.mobileUI, testIdBuilder = _a.testIdBuilder;
        var __ = this.props.translate;
        var date = selectedDate || (isEndDate ? viewDate.endOf('day') : viewDate);
        var inputs = [];
        var timeConstraints = this.timeConstraints;
        if (mobileUI) {
            return (React__default.createElement("div", { className: cx('CalendarTime') }, this.renderTimeViewPicker()));
        }
        timeFormat.split(':').forEach(function (format, i) {
            var type = /h/i.test(format)
                ? 'hours'
                : /m/.test(format)
                    ? 'minutes'
                    : /s/.test(format)
                        ? 'seconds'
                        : '';
            if (type) {
                var min_2 = timeConstraints[type].min;
                var max_2 = timeConstraints[type].max;
                var options_1 = _this.computedTimeOptions(type);
                var formatMap_1 = {
                    hours: 'HH',
                    minutes: 'mm',
                    seconds: 'ss'
                };
                inputs.push(React__default.createElement(Downshift, { key: i + 'input', inputValue: date.format(formatMap_1[type]) }, function (_a) {
                    var getInputProps = _a.getInputProps, openMenu = _a.openMenu, closeMenu = _a.closeMenu;
                    getInputProps({
                        onFocus: function () { return openMenu(); },
                        onChange: function (e) {
                            return _this.setTime(type, Math.max(min_2, Math.min(parseInt(e.currentTarget.value.replace(/\D/g, ''), 10) || 0, max_2)));
                        }
                    });
                    var itemTIB = testIdBuilder === null || testIdBuilder === void 0 ? void 0 : testIdBuilder.getChild(type);
                    return (React__default.createElement("div", { className: cx('CalendarInputWrapper') },
                        React__default.createElement("div", { className: cx('CalendarInput-sugs', type === 'hours'
                                ? 'CalendarInput-sugsHours'
                                : 'CalendarInput-sugsTimes'), id: "".concat(_this.state.uniqueTag, "-").concat(i, "-input") }, options_1.map(function (option) {
                            var _a;
                            return (React__default.createElement("div", __assign({ key: option.value, className: cx('CalendarInput-sugsItem', {
                                    'is-mobile': mobileUI,
                                    'is-highlight': selectedDate
                                        ? option.value === date.format(formatMap_1[type])
                                        : option.value === ((_a = options_1 === null || options_1 === void 0 ? void 0 : options_1[0]) === null || _a === void 0 ? void 0 : _a.value) &&
                                            !mobileUI
                                }) }, itemTIB === null || itemTIB === void 0 ? void 0 : itemTIB.getChild(option.value).getTestId(), { onClick: function () {
                                    _this.setTime(type, parseInt(option.value, 10));
                                    _this.scrollToTop(type, parseInt(option.value, 10), i);
                                    closeMenu();
                                } }), option.value));
                        }))));
                }));
                inputs.push(React__default.createElement("span", { key: i + 'divider' }));
            }
        });
        inputs.length && inputs.pop();
        var quickLists = [
            React__default.createElement("a", __assign({ key: "select-now", onClick: this.selectNowTime }, testIdBuilder === null || testIdBuilder === void 0 ? void 0 : testIdBuilder.getChild('select-now').getTestId()), __('TimeNow'))
        ];
        return (React__default.createElement(React__default.Fragment, null,
            React__default.createElement("div", { className: cx(timeRangeHeader ? 'TimeRangeHeaderWrapper' : null) }, timeRangeHeader),
            React__default.createElement("div", { className: cx('TimeContentWrapper') }, inputs),
            this.props.requiredConfirm && (React__default.createElement("div", { className: cx('TimeFooterWrapper') },
                React__default.createElement("div", { className: cx('QuickWrapper') }, quickLists),
                React__default.createElement("a", __assign({ className: cx('Button', 'Button--primary', 'Button--size-sm'), onClick: this.confirm }, testIdBuilder === null || testIdBuilder === void 0 ? void 0 : testIdBuilder.getChild('confirm').getTestId()), __('confirm'))))));
    };
    CustomTimeView.defaultProps = {
        showToolbar: true
    };
    return CustomTimeView;
}(React__default.Component));
var CustomTimeView$1 = localeable(CustomTimeView);

export { CustomTimeView, CustomTimeView$1 as default };
