import React from 'react';
import isSameDay from 'date-fns/isSameDay';
import setYear from 'date-fns/setYear';
import setMonth from 'date-fns/setMonth';
import setDate from 'date-fns/setDate';
import PopoverNext from '../PopoverNext';
import Calendar from '../Calendar';
import DateInput from './DateInput';
import Divider from '../Divider';
import { st, classes } from './DatePicker.st.css.js';
import { dataHooks, MAX_DATE } from './constants';
import { WixStyleReactEnvironmentContext } from '../WixStyleReactEnvironmentProvider/context';
import { SupportedWixLocales } from '@wix/design-systems-locale-utils';
import { ZIndex } from '../common/ZIndex';
import { generateID } from '../utils/generateId';
class DatePicker extends React.PureComponent {
    constructor(props) {
        super(props);
        this.componentDidUpdate = prevProps => {
            const { value: prevValue } = prevProps;
            const { value: newValue } = this.props;
            if (newValue !== prevValue) {
                if (newValue) {
                    if (newValue !== this.state.value) {
                        this.setState({ inputValue: newValue });
                    }
                    this._saveNewValue(newValue);
                    return;
                }
                const value = this._transformDate(new Date(), prevValue);
                return this.setState({ inputValue: null, value });
            }
        };
        this._openCalendar = () => {
            if (!this.state.isOpen &&
                !this.props.readOnly &&
                !this.props.disabled &&
                this.state.shouldOpenCalendar) {
                return this.setState({
                    isOpen: true,
                    value: this.props.value || new Date(),
                }, () => {
                    this.props.onOpen?.();
                });
            }
            if (!this.state.shouldOpenCalendar) {
                return this.setState({
                    shouldOpenCalendar: true,
                });
            }
        };
        this.openCalendar = this._openCalendar;
        this._closeCalendar = (shouldOpenCalendar = true, shouldFocusInput = false) => {
            this.setState({ isOpen: false, autoFocus: false, shouldOpenCalendar }, () => {
                this.props.onClose?.();
                if (shouldFocusInput) {
                    this.state.inputRef?.focus();
                }
            });
        };
        this._handleInputChange = ({ dateVal }) => {
            this._saveNewValue(dateVal);
        };
        this._transformDate = (value, oldValue) => [
            [value.getFullYear(), setYear],
            [value.getMonth(), setMonth],
            [value.getDate(), setDate],
        ].reduce((_value, [datePart, setter]) => setter(_value, datePart), oldValue);
        this._saveNewValue = (value, modifiers = {}) => {
            if (modifiers.disabled) {
                return;
            }
            const oldValue = this.props.value || new Date(new Date().setHours(0, 0, 0, 0));
            const newValue = this._transformDate(value, oldValue);
            if (!isSameDay(value, this.props.value)) {
                this.setState({ value: newValue }, () => this.props.onChange(newValue));
            }
        };
        this._filterDate = date => date < MAX_DATE && this.props.filterDate(date);
        this._handleKeyDown = (event, newDate) => {
            if (!this.state.isOpen) {
                this._openCalendar();
            }
            switch (event.key) {
                case 'Tab':
                case 'Escape': {
                    this._closeCalendar();
                    return;
                }
                case 'Enter': {
                    event.preventDefault();
                    if (newDate) {
                        const transformedDate = this._transformDate(newDate, new Date(new Date().setHours(0, 0, 0, 0)));
                        this.setState({
                            value: transformedDate,
                            inputValue: transformedDate,
                        }, () => this.props.onChange(transformedDate));
                    }
                    this._closeCalendar();
                    return;
                }
                case 'ArrowUp':
                case 'ArrowDown': {
                    event.preventDefault();
                    this.setState({ autoFocus: true });
                    return;
                }
                default:
                    return;
            }
        };
        this._handleCalendarKeyDown = event => {
            switch (event.key) {
                case 'Escape': {
                    event.stopPropagation();
                    this._closeCalendar(false, true);
                    return;
                }
                default:
                    return;
            }
        };
        this._handleChange = (value, modifiers) => {
            this.setState({
                inputValue: value,
                isOpen: !this.props.shouldCloseOnSelect || false,
                shouldOpenCalendar: !this.props.shouldCloseOnSelect || false,
            });
            this._saveNewValue(value, modifiers);
        };
        this._handleRef = ref => {
            this.setState({ inputRef: ref });
        };
        this._handleInputFocus = event => {
            if (!event.isTrusted) {
                return;
            }
            this._openCalendar();
            this.setState({ autoFocus: false }, () => {
                this.state.inputRef?.focus();
                this.props.inputProps?.onFocus?.(event);
            });
        };
        this._renderInput = () => {
            const { inputDataHook, disabled, placeholderText, readOnly, status, statusMessage, customInput, inputProps = {}, size, clearButton, onClear, disableKeyboardType, dateStyle, validate, onValidate, excludePastDates, clearButtonTooltipContent, clearButtonTooltipProps, clearButtonAriaLabel, } = this.props;
            const { onFocus, ...inputPropsRest } = inputProps;
            return (React.createElement(DateInput, { dataHook: inputDataHook, className: classes.input, value: this.state.inputValue, onInputClicked: this._openCalendar, disabled: disabled, readOnly: readOnly, placeholder: placeholderText, onFocus: this._handleInputFocus, onKeyDown: this._handleKeyDown, tabIndex: 0, status: status, statusMessage: statusMessage, autoSelect: false, customInput: customInput, locale: this._getLocale(), dateStyle: dateStyle, size: size, clearButton: clearButton, onClear: onClear, onChange: this._handleInputChange, disableEditing: disableKeyboardType, validate: validate, onValidate: onValidate, excludePastDates: excludePastDates, clearButtonTooltipContent: clearButtonTooltipContent, clearButtonTooltipProps: clearButtonTooltipProps, clearButtonAriaLabel: clearButtonAriaLabel, inputRef: this._handleRef, focusOnClearClick: true, ...(customInput ? customInput.props : {}), ...inputPropsRest }));
        };
        this._combineDataHooks = (start, end) => {
            return end ? `${start}-${end}` : start;
        };
        this.rootId = generateID();
        this.state = {
            value: props.value || new Date(),
            isOpen: props.initialOpen && !props.disabled,
            inputValue: props.value,
            autoFocus: false,
            shouldOpenCalendar: true,
        };
    }
    _getLocale() {
        return this.props.locale || this.context.locale || 'en';
    }
    render() {
        const { className, showMonthDropdown, showYearDropdown, excludePastDates, rtl, shouldCloseOnSelect, width, calendarDataHook, twoMonths, zIndex, dataHook, popoverProps, firstDayOfWeek, leftArrowAriaLabel, leftArrowAriaLabelledBy, rightArrowAriaLabel, rightArrowAriaLabelledBy, monthDropdownAriaLabel, monthDropdownAriaLabelledBy, yearDropdownAriaLabel, yearDropdownAriaLabelledBy, disableKeyboardType, dateIndication, disabled, renderFooter, } = this.props;
        const { isOpen, value } = this.state;
        const calendarProps = {
            dataHook: this._combineDataHooks(dataHooks.datePickerCalendar, this.props.dataHook),
            className: classes.calendar,
            locale: this._getLocale(),
            showMonthDropdown,
            showYearDropdown,
            filterDate: this._filterDate,
            excludePastDates,
            rtl,
            onChange: this._handleChange,
            onClose: () => this._closeCalendar(false),
            value,
            shouldCloseOnSelect,
            numOfMonths: twoMonths ? 2 : 1,
            firstDayOfWeek,
            leftArrowAriaLabel,
            leftArrowAriaLabelledBy,
            rightArrowAriaLabel,
            rightArrowAriaLabelledBy,
            monthDropdownAriaLabel,
            monthDropdownAriaLabelledBy,
            yearDropdownAriaLabel,
            yearDropdownAriaLabelledBy,
            dateIndication,
            autoFocus: this.state.autoFocus || false,
            containFocus: true,
            onKeyDown: this._handleCalendarKeyDown,
            size: this.props.calendarProps?.size,
        };
        return (React.createElement("div", { "data-date-picker-id": this.rootId, className: st(classes.root, { disableKeyboardType, disabled }, className), "data-hook": dataHook, style: { width } },
            React.createElement(PopoverNext, { className: classes.popover, dataHook: dataHooks.datePickerPopover, onOpenChange: (open, reason) => {
                    if (!open &&
                        (reason === 'outside-press' || reason === 'escape-key')) {
                        this._closeCalendar(false);
                    }
                }, appendTo: "parent", open: isOpen, zIndex: zIndex, tabIndex: -1, focusManagerEnabled: false, placement: rtl ? 'top-end' : 'top-start', ...popoverProps },
                React.createElement(PopoverNext.Trigger, null,
                    React.createElement("div", { className: classes.inputContainer }, this._renderInput())),
                React.createElement(PopoverNext.Content, null,
                    React.createElement("div", { "data-hook": calendarDataHook, "data-calendar-id": this.rootId },
                        React.createElement(Calendar, { ...calendarProps }),
                        renderFooter && (React.createElement(React.Fragment, null,
                            React.createElement(Divider, null),
                            React.createElement("div", { "data-hook": dataHooks.datePickerFooter, className: classes.footer }, renderFooter()))))))));
    }
}
DatePicker.displayName = 'DatePicker';
DatePicker.defaultProps = {
    filterDate: () => true,
    rtl: false,
    width: '150px',
    zIndex: ZIndex.datePicker,
    disabled: false,
    inputDataHook: dataHooks.datePickerInput,
    popoverProps: {
        zIndex: ZIndex.datePickerPopover,
    },
    disableKeyboardType: false,
    onChange: () => { },
    dateStyle: 'short',
    shouldCloseOnSelect: true,
};
export default DatePicker;
DatePicker.contextType = WixStyleReactEnvironmentContext;
//# sourceMappingURL=DatePicker.js.map