import React from 'react';
import { FocusScope } from '@react-aria/focus';
import addMonths from 'date-fns/addMonths';
import subMonths from 'date-fns/subMonths';
import startOfMonth from 'date-fns/startOfMonth';
import isSameDay from 'date-fns/isSameDay';
import { SupportedWixLocales } from '@wix/design-systems-locale-utils';
import { CalendarView } from './utils';
import localeUtilsFactory from '../common/LocaleUtils/LocaleUtils';
import BaseCalendar from './BaseCalendar/BaseCalendar';
import DatePickerHead from './DatePickerHead';
import { WixStyleReactEnvironmentContext } from '../WixStyleReactEnvironmentProvider/context';
import { st, classes } from './Calendar.st.css.js';
import { dataHooks } from './constants';
class Calendar extends React.PureComponent {
    constructor(props) {
        super(props);
        this._setMonth = month => {
            this.setState({ month });
            const { onMonthChange } = this.props;
            if (onMonthChange) {
                onMonthChange(month);
            }
        };
        this._getLocaleUtilsFactory = (locale, firstDayOfWeek) => {
            return localeUtilsFactory(locale, firstDayOfWeek);
        };
        this._createCaptionElement = () => {
            const { showMonthDropdown, showYearDropdown, leftArrowAriaLabel, leftArrowAriaLabelledBy, rightArrowAriaLabel, rightArrowAriaLabelledBy, monthDropdownAriaLabel, monthDropdownAriaLabelledBy, yearDropdownAriaLabel, yearDropdownAriaLabelledBy, size, } = this.props;
            const { month } = this.state;
            const locale = this._getLocale();
            const localeUtils = this._getLocaleUtilsFactory(locale);
            return (React.createElement(DatePickerHead, { className: classes.header,
                date: month,
                showYearDropdown,
                showMonthDropdown,
                locale: typeof locale === 'string' ? locale : '',
                localeUtils,
                onChange: this._setMonth,
                onLeftArrowClick: () => this._setMonth(startOfMonth(addMonths(month, -1))),
                onRightArrowClick: () => this._setMonth(startOfMonth(addMonths(month, 1))),
                leftArrowAriaLabel,
                leftArrowAriaLabelledBy,
                rightArrowAriaLabel,
                rightArrowAriaLabelledBy,
                monthDropdownAriaLabel,
                monthDropdownAriaLabelledBy,
                yearDropdownAriaLabel,
                yearDropdownAriaLabelledBy,
                size }));
        };
        const initialMonth = Calendar.getUpdatedMonth(props.value, props.numOfMonths);
        this.state = {
            month: initialMonth || new Date(),
        };
    }
    UNSAFE_componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.props.value) {
            const month = Calendar.getUpdatedMonth(nextProps.value, nextProps.numOfMonths, this.state.month);
            if (month) {
                this.setState({ month });
            }
        }
    }
    static areValuesEqual(value1 = {}, value2 = {}) {
        if (!Boolean(value1) && !Boolean(value2)) {
            return true;
        }
        if (Calendar.isRangeValue(value1) && Calendar.isRangeValue(value2)) {
            return (isSameDay(value1.from, value2.from) && isSameDay(value1.to, value2.to));
        }
        return isSameDay(value1, value2);
    }
    static isSingleDay(value) {
        return value instanceof Date;
    }
    static isRangeValue(value) {
        return Boolean(value.from || value.to);
    }
    _getLocale() {
        return this.props.locale || this.context.locale || 'en';
    }
    render() {
        const { dataHook, className, autoFocus, numOfMonths, firstDayOfWeek, onChange, onClose, excludePastDates, filterDate, value, selectionMode, shouldCloseOnSelect, locale, rtl, dateIndication, today, size, onKeyDown, containFocus, } = this.props;
        const { month } = this.state;
        return (React.createElement("div", null,
            React.createElement(FocusScope, { contain: autoFocus && containFocus, restoreFocus: containFocus },
                React.createElement(BaseCalendar, { dataHook: dataHook || dataHooks.baseCalendar, size: size, className: st(classes.root, className), autoFocus: autoFocus, numOfMonths: numOfMonths, firstDayOfWeek: firstDayOfWeek, onChange: onChange, onClose: onClose, excludePastDates: excludePastDates, filterDate: filterDate, value: value, selectionMode: selectionMode, shouldCloseOnSelect: shouldCloseOnSelect, locale: locale, rtl: rtl, dateIndication: dateIndication, today: today, onDisplayedViewChange: this._setMonth, displayedMonth: month, captionElement: this._createCaptionElement(), onKeyDown: onKeyDown }))));
    }
}
Calendar.displayName = 'Calendar';
Calendar.defaultProps = {
    className: '',
    filterDate: () => true,
    dateIndication: () => null,
    shouldCloseOnSelect: true,
    onClose: () => { },
    autoFocus: true,
    excludePastDates: false,
    selectionMode: 'day',
    showMonthDropdown: false,
    showYearDropdown: false,
    numOfMonths: 1,
    size: 'medium',
};
Calendar.optionalParse = BaseCalendar.optionalParse;
/** Return a value in which all string-dates are parsed into Date objects */
Calendar.parseValue = BaseCalendar.parseValue;
Calendar.nextDay = BaseCalendar.nextDay;
Calendar.prevDay = BaseCalendar.prevDay;
Calendar.getUpdatedMonth = (nextPropsValue, numOfMonths, currentMonthDate) => {
    const nextValue = Calendar.parseValue(nextPropsValue);
    if (!currentMonthDate) {
        return Calendar.isSingleDay(nextValue)
            ? nextValue
            : nextValue.from || nextValue.to;
    }
    const view = new CalendarView(currentMonthDate, numOfMonths);
    if (Calendar.isSingleDay(nextValue)) {
        if (!view.isContained(nextValue)) {
            return nextValue;
        }
    }
    else {
        const { from, to } = nextValue;
        if (from && view.isAfterView(from)) {
            //         F--- =>  F---
            //   VVVVV      =>  VVVVV
            return from;
        }
        else if (to && view.isBeforeView(to)) {
            if (view.isRangeFits(from, to)) {
                //   F-T        =>  F-T
                //       VVVVV  =>  VVVVV
                return from;
            }
            else {
                //   F-----T        =>  F-----T
                //          VVVVV    =>    VVVVV
                return subMonths(to, numOfMonths - 1);
            }
        }
        else if (from &&
            view.isBeforeView(from) &&
            to &&
            view.isAfterView(to)) {
            //   F-------T  =>    F-------T
            //     VVVVV    =>    VVVVV
            return from; // choose the 'from' anchor arbitrarily
        }
    }
    /*
     * We only changed the month if the day (or range.edges) are outside the view.
     * This is to avoid changing the month right after a user clicks on the calendar.
     */
    return null;
};
export default Calendar;
Calendar.contextType = WixStyleReactEnvironmentContext;
//# sourceMappingURL=Calendar.js.map