import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useEffect, useRef } from 'react';
import Flex from '../../Flex';
import MonthInput from '../Input/MonthInput';
import Icon, { registerIcon } from '../../Icon';
import * as caretLeftIcon from '../../Icon/icons/caret-left.icon';
import * as caretRightIcon from '../../Icon/icons/caret-right.icon';
import { useConfiguration, useDirection, useI18n, useTestIds } from '../../../hooks';
import { getSelectedDateInfoText, getCalendarTypeFromLocale, parseToDate } from '../Input/utils';
import { CALENDAR_TYPES } from '../Input/local';
import TimeInput from '../Input/TimeInput';
import VisuallyHiddenText from '../../VisuallyHiddenText';
import { getDatePickerTestIds } from '../DateTime.test-ids';
import { withTestIds } from '../../../utils';
import { getAdjustedUTCDateTime } from '../utils';
import Calendar from './Calendar';
import { shiftDateByMonth, isValidDate, toDateTimeString, getCurrentMonthYearLabel } from './utils';
import { StyledDatePicker, StyledDatePickerMonthInput, StyledMonthPicker, StyledMonthNavigationButton } from './DatePicker.styles';
registerIcon(caretLeftIcon, caretRightIcon);
const DatePicker = ({ testId, selected: initial, onChange, min, max, mode = 'date', showWeekNumber, withSeconds, pickerInterval, clockFormat, ...restProps }) => {
    const testIds = useTestIds(testId, getDatePickerTestIds);
    const { locale } = useConfiguration();
    const t = useI18n();
    const [selected, setSelected] = useState(initial);
    const [current, setCurrent] = useState(selected && isValidDate(selected) ? selected : getAdjustedUTCDateTime());
    useEffect(() => {
        if (toDateTimeString(initial, mode) !== toDateTimeString(selected, mode)) {
            setSelected(initial);
            setCurrent(initial || getAdjustedUTCDateTime());
        }
    }, [toDateTimeString(initial, mode)]);
    const calendarRef = useRef(null);
    useEffect(() => {
        // need to postpone focusing to make sure onFocusWithin has been attached
        setTimeout(() => {
            calendarRef.current?.querySelector('button[tabindex="0"]:enabled')?.focus();
        });
    }, []);
    const getTodayButtonLabel = () => {
        if (mode === 'datetime') {
            return t('set_current_date_and_time_a11y');
        }
        if (mode === 'week') {
            return t('set_current_week_ally');
        }
        return t('set_current_date_a11y');
    };
    const todayButtonLabel = getTodayButtonLabel();
    const calendarType = mode === 'week' ? CALENDAR_TYPES.ISO_8601 : getCalendarTypeFromLocale(locale);
    const { start, end } = useDirection();
    return (_jsxs(StyledDatePicker, { "data-testid": testIds.root, "aria-label": t('calendar'), role: 'region', ...restProps, children: [_jsxs(Flex, { as: StyledMonthPicker, container: { justify: 'between', alignItems: 'end' }, children: [_jsx(MonthInput, { testId: testIds.month, as: StyledDatePickerMonthInput, innerLabelsHidden: false, value: current, required: true, role: 'group', "aria-label": t('picker_jump_to_month_and_year'), onChange: ({ valueAsTimestamp }) => {
                            let newCurrent = new Date(valueAsTimestamp);
                            if (max) {
                                const maxDate = parseToDate(max);
                                if (newCurrent > maxDate)
                                    newCurrent = maxDate;
                            }
                            if (min) {
                                const minDate = parseToDate(min);
                                if (newCurrent < minDate)
                                    newCurrent = minDate;
                            }
                            setCurrent(newCurrent);
                        }, min: min, max: max }), _jsx(VisuallyHiddenText, { "aria-live": 'polite', role: 'alert', children: selected === current
                            ? getSelectedDateInfoText(current, mode, locale, t)
                            : getCurrentMonthYearLabel(current, locale) }), _jsx(StyledMonthNavigationButton, { "data-testid": testIds.previousMonth, label: t('picker_prev_month'), variant: 'simple', icon: true, onClick: () => {
                            const newCurrent = shiftDateByMonth(current, -1);
                            setCurrent(newCurrent);
                        }, disabled: (() => {
                            const newCurrent = new Date(current);
                            newCurrent.setUTCDate(1);
                            return Boolean(min && min > newCurrent);
                        })(), children: _jsx(Icon, { name: `caret-${start}` }) }), _jsx(StyledMonthNavigationButton, { "data-testid": testIds.setCurrentDate, label: todayButtonLabel, icon: true, variant: 'simple', onClick: () => {
                            const currDate = getAdjustedUTCDateTime();
                            setCurrent(currDate);
                            setSelected(currDate);
                            onChange?.(currDate);
                        }, children: _jsx(Icon, { name: 'calendar-now' }) }), _jsx(StyledMonthNavigationButton, { "data-testid": testIds.nextMonth, label: t('picker_next_month'), icon: true, variant: 'simple', onClick: () => {
                            const nextCurrent = shiftDateByMonth(current, +1);
                            setCurrent(nextCurrent);
                        }, disabled: (() => {
                            const newCurrent = new Date(current);
                            newCurrent.setUTCMonth(newCurrent.getUTCMonth() + 1);
                            newCurrent.setUTCDate(0);
                            return Boolean(max && max < newCurrent);
                        })(), children: _jsx(Icon, { name: `caret-${end}` }) })] }), _jsx(Flex, { container: { wrap: 'nowrap' }, dir: 'ltr', children: _jsx(Calendar, { testId: testIds.calendar, ref: calendarRef, selected: selected && isValidDate(selected) ? selected : undefined, current: current, calendarType: calendarType, showWeekNumber: showWeekNumber, mode: mode === 'datetime' ? 'date' : mode, onFocus: setCurrent, onSelect: selectedDate => {
                        const newDate = new Date(selectedDate);
                        if (selected) {
                            newDate.setUTCHours(selected.getUTCHours());
                            newDate.setUTCMinutes(selected.getUTCMinutes());
                            newDate.setUTCSeconds(selected.getUTCSeconds());
                        }
                        setCurrent(newDate);
                        setSelected(newDate);
                        onChange?.(newDate);
                    }, min: min, max: max }) }), mode === 'datetime' && (_jsx(TimeInput, { testId: testIds.time, label: t('time_text'), value: selected, pickerInterval: pickerInterval, withSeconds: withSeconds, clockFormat: clockFormat, onChange: selectedTime => {
                    if (selectedTime.state || !selectedTime.valueAsISOString) {
                        return;
                    }
                    const newDate = selected ? new Date(selected) : new Date();
                    const selectedTimeDateObject = new Date(selectedTime.valueAsISOString);
                    newDate.setUTCHours(selectedTimeDateObject.getUTCHours());
                    newDate.setUTCMinutes(selectedTimeDateObject.getUTCMinutes());
                    newDate.setUTCSeconds(selectedTimeDateObject.getUTCSeconds());
                    setSelected(newDate);
                    onChange?.(newDate);
                }, min: min, max: max }))] }));
};
export default withTestIds(DatePicker, getDatePickerTestIds);
//# sourceMappingURL=DatePicker.js.map