"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Datepicker = void 0;
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const OverlayTrigger_1 = tslib_1.__importDefault(require("../OverlayTrigger"));
const react_1 = require("react");
const useProperty_1 = tslib_1.__importDefault(require("../utils/useProperty"));
const FieldWrap_1 = tslib_1.__importDefault(require("../FieldWrap"));
const SimpleButton_1 = tslib_1.__importDefault(require("../SimpleButton"));
const rebass_1 = require("rebass");
const FormatHelper_1 = require("../../Utilities/Helpers/FormatHelper");
const DatepickerContext_1 = require("./DatepickerContext");
const react_day_picker_1 = require("react-day-picker");
const AdaptableDateInlineInput_1 = require("../../View/Components/AdaptableInput/AdaptableDateInlineInput");
const date_fns_1 = require("date-fns");
const Select_1 = require("../Select");
const onDatePickerDropdownKeyDown = (e) => {
    if (e.key === 'Escape' || e.key === 'Enter') {
        e.stopPropagation();
    }
};
const DatePickerComponents = {
    YearsDropdown: (props) => {
        const onChange = (0, react_1.useCallback)((value) => {
            props.onChange?.({
                target: {
                    value,
                },
            });
        }, [props.onChange]);
        return (React.createElement(Select_1.Select, { onKeyDown: onDatePickerDropdownKeyDown, value: props.value, onChange: onChange, options: props.options }));
    },
    MonthsDropdown: (props) => {
        const onChange = (0, react_1.useCallback)((value) => {
            props.onChange?.({
                target: {
                    value,
                },
            });
        }, [props.onChange]);
        return (React.createElement(Select_1.Select, { onKeyDown: onDatePickerDropdownKeyDown, value: `${props.value}`, onChange: onChange, options: props.options.map((option) => {
                return {
                    label: option.label,
                    value: `${option.value}`,
                };
            }) }));
    },
};
const DatepickerOverlay = ({ onHide, children, onKeyDown, onMouseDown, overlayDOMRef, }) => {
    const domRef = React.useRef(null);
    return (React.createElement("div", { className: "ab-Datepicker-Overlay", tabIndex: -1, ref: (el) => {
            domRef.current = el;
            overlayDOMRef.current = el;
        }, onKeyDown: onKeyDown, onMouseDown: onMouseDown, onBlur: (e) => {
            const { relatedTarget } = e;
            const node = domRef.current;
            // relatedTarget is the newly focused element as a result of this blur event
            // so we close the overlay when the newly focused element is outside the overlay
            if (relatedTarget == null || !node.contains?.(relatedTarget)) {
                onHide();
            }
        } }, children));
};
const END_MONTH = (0, date_fns_1.endOfYear)((0, date_fns_1.addYears)(new Date(), 10));
const START_MONTH = (0, date_fns_1.startOfYear)((0, date_fns_1.addYears)(new Date(), -50));
exports.Datepicker = React.forwardRef((props, ref) => {
    const { dateProps, required, disabled, style, placeholder, showWeekNumber, showOutsideDays, value: _, defaultValue: __, onChange: ___, datepickerButtons, showClearButton, autoFocus, ...boxProps } = props;
    const datepickerContext = (0, DatepickerContext_1.useDatepickerContext)();
    let [value, setValue] = (0, useProperty_1.default)(props, 'value', undefined, {
        onChange: props.onChange,
    });
    (0, react_1.useEffect)(() => {
        // when value is reset, also reset the month to the current month
        if (!value) {
            setMonth(new Date());
        }
    }, [!!value]);
    const [month, setMonth] = (0, react_1.useState)(value ?? new Date());
    const updateValue = (value) => {
        setValue(value);
        setMonth(value ?? new Date());
    };
    const inputValue = (0, FormatHelper_1.DateFormatter)(value, { Pattern: dateProps.format }) ?? '';
    const [visible, doSetVisible] = (0, react_1.useState)(false);
    const setVisible = (visible, keyboardEventKey) => {
        doSetVisible(visible);
        if (!visible) {
            datepickerContext?.onHide?.(keyboardEventKey);
        }
        else {
            datepickerContext?.onShow?.();
        }
    };
    const clearValue = () => {
        updateValue(undefined);
    };
    const renderButton = (label, onClick) => (React.createElement(SimpleButton_1.default, { onClick: onClick, margin: '2px' }, label));
    const todayDate = new Date();
    const footerButtonsMap = {
        clear: renderButton('Clear', () => clearValue()),
        close: renderButton('Close', () => setVisible(false)),
        today: renderButton('Today', () => updateValue(todayDate)),
        tomorrow: renderButton('Tomorrow', () => updateValue((0, date_fns_1.addDays)(todayDate, 1))),
        yesterday: renderButton('Yesterday', () => updateValue((0, date_fns_1.addDays)(todayDate, -1))),
        nextWorkday: renderButton('Next Workday', () => updateValue((0, date_fns_1.addBusinessDays)(todayDate, 1))),
        prevWorkday: renderButton('Prev Workday', () => updateValue((0, date_fns_1.addBusinessDays)(todayDate, -1))),
        '-': React.createElement("div", { style: { flex: '1 1 1%' } }),
        '|': React.createElement("hr", { style: { width: '100%', height: 0, margin: 0, border: 'none' } }),
    };
    const footerButtons = datepickerButtons.map((buttonKey, index) => React.cloneElement(footerButtonsMap[buttonKey], { key: index }));
    const clearButton = showClearButton !== false ? (React.createElement(SimpleButton_1.default, { "data-name": "clear", variant: "text", tooltip: "Clear", iconSize: 20, padding: 0, icon: "close", onMouseDown: (e) => {
            e.preventDefault();
            clearValue();
        }, accessLevel: 'Full' })) : null;
    const calendarButton = (React.createElement(SimpleButton_1.default, { disabled: disabled, variant: "text", icon: "calendar", tooltip: "Date", iconSize: 20, px: 0, py: 0, onClick: () => setVisible(true) }));
    const overlayDOMRef = (0, react_1.useRef)(null);
    return (React.createElement(rebass_1.Flex, null,
        React.createElement(OverlayTrigger_1.default, { visible: visible, render: () => (React.createElement(DatepickerOverlay, { overlayDOMRef: overlayDOMRef, onMouseDown: props.onMouseDown, onHide: () => setVisible(false), onKeyDown: (e) => {
                    if (e.key === 'Escape' || e.key === 'Enter') {
                        setVisible(false, e.key);
                    }
                } },
                React.createElement(react_day_picker_1.DayPicker, { fixedWeeks: true, autoFocus: autoFocus ?? true, showWeekNumber: showWeekNumber, showOutsideDays: showOutsideDays, mode: "single", captionLayout: "dropdown", month: isNaN(+month) ? new Date() : month, selected: value, onMonthChange: setMonth, onSelect: updateValue, startMonth: START_MONTH, endMonth: END_MONTH, components: DatePickerComponents, footer: React.createElement(rebass_1.Flex, { justifyContent: "space-between", mt: 2, flexWrap: 'wrap' }, footerButtons) }))) },
            React.createElement(FieldWrap_1.default, { ...boxProps, style: {
                    borderRadius: style?.borderRadius,
                    width: style?.width,
                    maxWidth: style?.maxWidth,
                    border: style?.border,
                }, className: "ab-Datepicker", onFocus: () => {
                    if (!visible) {
                        setVisible(true);
                    }
                }, onBlur: (e) => {
                    const { relatedTarget } = e;
                    const overlayDOMNode = overlayDOMRef.current;
                    if ((overlayDOMNode && relatedTarget == overlayDOMNode) ||
                        overlayDOMNode?.contains(relatedTarget)) {
                        return;
                    }
                    setVisible(false);
                } },
                React.createElement(AdaptableDateInlineInput_1.AdaptableDateInlineInput, { ref: ref, value: inputValue, 
                    // We do not want to show the format when the date-picker is visible
                    placeholder: placeholder ?? '', onChange: (value) => {
                        const date = new Date(value);
                        if ((0, date_fns_1.isValid)(date)) {
                            updateValue(date);
                        }
                    }, style: style, disabled: disabled }),
                !!inputValue ? clearButton : null,
                calendarButton))));
});
