import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { forwardRef, Fragment, useRef, useState } from 'react';
import styled, { css } from 'styled-components';
import { defaultThemeProp } from '../../../theme';
import { useConfiguration, useConsolidatedRef, useFocusWithin, useI18n, useOuterEvent, useTestIds, useUID } from '../../../hooks';
import { cap, createClassName, withTestIds } from '../../../utils';
import FormField from '../../FormField';
import Icon, { registerIcon } from '../../Icon';
import * as calendarIcon from '../../Icon/icons/calendar.icon';
import Flex from '../../Flex';
import { StyledFormControl } from '../../FormControl';
import DatePicker from '../Picker/DatePicker';
import { getWeekInputTestIds } from '../DateTime.test-ids';
import HiddenText from '../../HiddenText';
import { parseToDate, getWeekYear, getWeek, generatePickerButtonAriaLabel, convertWeekYearToDate } from './utils';
import StyledDateTime, { BareInput, StyledDatePickerDialog, StyledDialogContent, StyledInputButton, StyledInputContainer } from './DateTime.styles';
import usePickerButton from './usePickerButton';
import PartInput from './PartInput';
import useAutoFocusNextInput from './useAutoFocusNextInput';
registerIcon(calendarIcon);
export const StyledWeekInput = styled(StyledDateTime)(props => {
    const { theme: { base } } = props;
    return css `
    padding-inline-end: 0;

    ${StyledInputContainer} > ${BareInput}:first-of-type {
      margin-inline-start: ${base.spacing};
    }
  `;
});
StyledWeekInput.defaultProps = defaultThemeProp;
const convertToCallbackParameter = (date, parts) => {
    if ([parts.week, parts.year].every(Boolean)) {
        const { year, month, day } = convertWeekYearToDate(parts) ?? {};
        date.setUTCFullYear(Number(year), Number(month), Number(day));
        return {
            valueAsISOString: date.toISOString(),
            valueAsTimestamp: date.getTime()
        };
    }
    if ([parts.week, parts.year].every(p => !p)) {
        return {
            valueAsISOString: undefined,
            valueAsTimestamp: undefined
        };
    }
    return {
        valueAsISOString: '',
        valueAsTimestamp: NaN,
        state: 'incomplete'
    };
};
const WeekInput = forwardRef(function WeekInput(props, ref) {
    const { testId, value, min, max, id, label, labelHidden, status, info, required, readOnly, disabled, onChange, onFocus, onBlur, autoFocus, additionalInfo, className, ...restProps } = props;
    const testIds = useTestIds(testId, getWeekInputTestIds);
    const { locale } = useConfiguration();
    const t = useI18n();
    const yearPartId = useUID();
    const containerRef = useConsolidatedRef(ref);
    const date = value !== undefined ? parseToDate(value) : undefined;
    const [hasValue, setHasValue] = useState(!!date);
    const [weekInputRef, yearInputRef] = [
        useRef(null),
        useRef(null)
    ];
    const { description, descriptionID } = useAutoFocusNextInput([weekInputRef, yearInputRef]);
    const pickParts = () => {
        return {
            week: weekInputRef.current?.value || undefined,
            year: yearInputRef.current?.value || undefined
        };
    };
    const currentlySelectedDate = () => {
        const dateParts = convertWeekYearToDate(pickParts());
        if (dateParts) {
            const year = Number(dateParts.year);
            const month = Number(dateParts.month);
            const day = Number(dateParts.day);
            const current = date ?? new Date();
            return new Date(current.setUTCFullYear(year ?? current.getUTCFullYear(), month ?? current.getUTCMonth(), day ?? current.getUTCDate()));
        }
    };
    const inputContainerRef = useRef(null);
    const onFocusChange = (focused) => {
        const callbackParam = convertToCallbackParameter(date ? new Date(date) : new Date(), pickParts());
        if (onFocus && focused)
            onFocus(callbackParam);
        if (!focused) {
            if (inputContainerRef.current)
                inputContainerRef.current.scrollTop = 0;
            onBlur?.(callbackParam);
        }
    };
    const [open, setOpen, , setPopoverRef, buttonEl, setButtonEl] = usePickerButton();
    const onInputChange = () => {
        onChange?.(convertToCallbackParameter(date ? new Date(date) : new Date(), pickParts()));
        buttonEl?.setAttribute('aria-label', generatePickerButtonAriaLabel(currentlySelectedDate(), 'week', locale, t, open));
        if (weekInputRef.current?.value !== '' && yearInputRef.current?.value !== '') {
            setHasValue(true);
        }
        else {
            setHasValue(false);
        }
    };
    // autoclose picker on focusing out
    useOuterEvent('focusin', [containerRef], e => {
        if (containerRef.current?.contains(e.relatedTarget))
            setOpen(false);
    });
    const displayNames = new Intl.DisplayNames(locale, {
        style: 'long',
        type: 'dateTimeField'
    });
    const WeekNumberInput = (_jsx(PartInput, { "data-testid": testIds.controlWeek, placeholder: t('week_placeholder'), "aria-label": displayNames.of('weekOfYear'), value: date ? getWeek(date, undefined, 'UTC') : undefined, onChange: onInputChange, size: 2, maxLength: 2, min: 1, max: 53, readOnly: readOnly, ref: weekInputRef, autoFocus: autoFocus }, 'week'));
    const YearInput = (_jsxs(Fragment, { children: [_jsx(PartInput, { "data-testid": testIds.controlYear, placeholder: t('year_placeholder'), "aria-label": displayNames.of('year'), "aria-describedby": yearPartId, value: date ? getWeekYear(date, undefined, 'UTC') : undefined, onChange: onInputChange, size: 4, maxLength: 4, min: 1, max: 9999, readOnly: readOnly, ref: yearInputRef }), _jsx(HiddenText, { id: yearPartId, children: t('year_input_description') })] }, 'year'));
    useFocusWithin([containerRef], onFocusChange);
    const Picker = (_jsxs(_Fragment, { children: [_jsx(StyledInputButton, { "data-testid": testIds.openClosePicker, variant: 'simple', icon: true, ref: setButtonEl, onClick: () => setOpen(cur => !cur), "aria-label": generatePickerButtonAriaLabel(currentlySelectedDate(), 'week', locale, t, open), readOnly: readOnly, disabled: disabled, children: _jsx(Icon, { name: 'calendar' }) }), open && buttonEl && (_jsx(StyledDatePickerDialog, { ref: setPopoverRef, target: buttonEl, "aria-label": t('choose_week'), children: _jsx(Flex, { container: { direction: 'column' }, as: StyledDialogContent, children: _jsx(DatePicker, { testId: testIds.picker, selected: currentlySelectedDate(), onChange: selected => {
                            weekInputRef.current.value =
                                (selected && getWeek(selected, undefined, 'UTC').toString().padStart(2, '0')) ||
                                    '';
                            yearInputRef.current.value =
                                (selected && getWeekYear(selected, undefined, 'UTC').toString()) || '';
                            setOpen(false);
                            setTimeout(() => buttonEl?.focus());
                            onInputChange();
                        }, min: min, max: max, mode: 'week' }) }) }))] }));
    const Comp = (_jsxs(Flex, { "data-testid": label ? undefined : testIds.root, as: StyledWeekInput, forwardedAs: StyledFormControl, container: { alignItems: 'center', wrap: 'nowrap', justify: 'between' }, status: status, readOnly: readOnly, disabled: disabled, ref: containerRef, onClick: (e) => {
            if (e.target === containerRef.current)
                weekInputRef.current?.focus();
        }, ...restProps, className: createClassName('week-input', className), children: [_jsxs(Flex, { ref: inputContainerRef, as: StyledInputContainer, container: { alignItems: 'center', wrap: 'wrap' }, children: [cap(displayNames.of('weekOfYear')), " ", WeekNumberInput, ",", YearInput] }), !readOnly && (_jsxs(Flex, { container: true, children: [hasValue && (_jsx(StyledInputButton, { "data-testid": testIds.clearCurrentWeek, "aria-label": t('clear_current_date'), icon: true, onClick: () => {
                            weekInputRef.current.value = '';
                            yearInputRef.current.value = '';
                            setTimeout(() => buttonEl?.focus());
                            onInputChange();
                        }, variant: 'simple', compact: true, label: t('clear'), children: _jsx(Icon, { name: 'times' }) })), Picker] }))] }));
    return label ? (_jsxs(_Fragment, { children: [_jsx(FormField, { testId: testIds, as: 'fieldset', labelAs: 'legend', label: label, labelHidden: labelHidden, id: id, info: info, status: status, required: required, disabled: disabled, additionalInfo: additionalInfo, "aria-describedby": descriptionID, ref: ref, children: Comp }), description] })) : (Comp);
});
export default withTestIds(WeekInput, getWeekInputTestIds);
//# sourceMappingURL=WeekInput.js.map