import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
/**
 * Copyright (c) 2020-present, Goldman Sachs
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { BasePopover, BaseRadioGroup, CustomSelectorInput, clsx, } from '@finos/legend-art';
import { PRIMITIVE_TYPE } from '@finos/legend-graph';
import { guaranteeNonNullable, parseNumber, returnUndefOnError, } from '@finos/legend-shared';
import { useEffect, useRef, useState } from 'react';
import { useApplicationStore } from '@finos/legend-application';
import { buildCustomDateOption, buildDatePickerOption, CUSTOM_DATE_DAY_OF_WEEK, CUSTOM_DATE_FIRST_DAY_OF_UNIT, CUSTOM_DATE_OPTION_DIRECTION, CUSTOM_DATE_OPTION_REFERENCE_MOMENT, CUSTOM_DATE_OPTION_UNIT, CUSTOM_DATE_PICKER_OPTION, CustomDateOption, CustomFirstDayOfOption, CustomPreviousDayOfWeekOption, DatePickerOption, reservedCustomDateOptions, } from './CustomDatePickerHelper.js';
const AbsoluteDateValueSpecificationEditor = (props) => {
    const { valueSpecification, valueSelector, updateValueSpecification, setDatePickerOption, } = props;
    const inputRef = useRef(null);
    const absoluteDateValue = valueSelector(valueSpecification);
    const updateAbsoluteDateValue = (event) => {
        updateValueSpecification(valueSpecification, event.target.value, {
            primitiveTypeEnum: PRIMITIVE_TYPE.STRICTDATE,
        });
        setDatePickerOption(new DatePickerOption(event.target.value, CUSTOM_DATE_PICKER_OPTION.ABSOLUTE_DATE));
    };
    useEffect(() => {
        inputRef.current?.focus();
    }, []);
    return (_jsx("div", { className: "value-spec-editor__date-picker__absolute-date", children: _jsx("input", { ref: inputRef, className: "panel__content__form__section__input value-spec-editor__date-picker__absolute-date__input input--dark", type: "date", spellCheck: false, value: absoluteDateValue ?? '', onChange: updateAbsoluteDateValue }) }));
};
const AbsoluteTimeValueSpecificationEditor = (props) => {
    const { valueSpecification, valueSelector, updateValueSpecification, setDatePickerOption, } = props;
    const inputRef = useRef(null);
    const absoluteTimeValue = valueSelector(valueSpecification);
    const updateAbsoluteTimeValue = (event) => {
        const value = new Date(event.target.value).getUTCSeconds()
            ? event.target.value
            : `${event.target.value}:00`;
        updateValueSpecification(valueSpecification, value, {
            primitiveTypeEnum: PRIMITIVE_TYPE.DATETIME,
        });
        setDatePickerOption(new DatePickerOption(event.target.value, CUSTOM_DATE_PICKER_OPTION.ABSOLUTE_TIME));
    };
    useEffect(() => {
        inputRef.current?.focus();
    }, []);
    return (_jsx("div", { className: "value-spec-editor__date-picker__absolute-date", children: _jsx("input", { ref: inputRef, className: "panel__content__form__section__input value-spec-editor__date-picker__absolute-date__input input--dark", 
            // Despite its name this would actually allow us to register time in UTC
            // See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local#setting_timezones
            type: "datetime-local", 
            // Configure the step to show seconds picker
            // See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local#step
            step: "1", spellCheck: false, value: absoluteTimeValue ?? '', onChange: updateAbsoluteTimeValue }) }));
};
const CustomDateInstanceValueEditor = (props) => {
    const { customDateOptionValue, updateValueSpecification, setDatePickerOption, } = props;
    const applicationStore = useApplicationStore();
    const inputRef = useRef(null);
    const [durationValue, setDurationValue] = useState(customDateOptionValue.duration);
    const [unitValue, setUnitValue] = useState(customDateOptionValue.unit ?? CUSTOM_DATE_OPTION_UNIT.DAYS);
    const [directionValue, setDirectionValue] = useState(customDateOptionValue.direction ?? CUSTOM_DATE_OPTION_DIRECTION.BEFORE);
    const [referenceMomentValue, setReferenceMomentValueValue] = useState(customDateOptionValue.referenceMoment ??
        CUSTOM_DATE_OPTION_REFERENCE_MOMENT.TODAY);
    const changeValue = (latestDurationValue, latestUnitValue, latestDirectionValue, latestReferenceMomentValue) => {
        if (latestDurationValue !== 0 &&
            latestUnitValue !== '' &&
            latestDirectionValue !== '' &&
            latestReferenceMomentValue !== '') {
            const dateOption = new CustomDateOption(CUSTOM_DATE_PICKER_OPTION.CUSTOM_DATE, CUSTOM_DATE_PICKER_OPTION.CUSTOM_DATE, latestDurationValue, latestUnitValue, latestDirectionValue, latestReferenceMomentValue);
            updateValueSpecification(undefined, dateOption);
            const matchedPreservedCustomAdjustDates = reservedCustomDateOptions.filter((t) => t.generateDisplayLabel() === dateOption.generateDisplayLabel());
            if (matchedPreservedCustomAdjustDates.length > 0) {
                dateOption.label = guaranteeNonNullable(matchedPreservedCustomAdjustDates[0]?.label);
                dateOption.value = guaranteeNonNullable(matchedPreservedCustomAdjustDates[0]?.value);
            }
            else {
                dateOption.updateLabel();
            }
            setDatePickerOption(dateOption);
        }
    };
    const changeDurationValue = (event) => {
        const duration = event.target.value !== ''
            ? (returnUndefOnError(() => parseNumber(event.target.value)) ?? 0)
            : 0;
        setDurationValue(duration);
        changeValue(duration, unitValue, directionValue, referenceMomentValue);
    };
    useEffect(() => {
        inputRef.current?.focus();
    }, []);
    return (_jsxs("div", { className: "value-spec-editor__date-picker__custom-date", children: [_jsx("div", { className: "value-spec-editor__date-picker__custom-date__input", children: _jsx("input", { ref: inputRef, className: "value-spec-editor__date-picker__custom-date__input-text-editor input--dark", spellCheck: false, value: durationValue, type: "number", onChange: changeDurationValue }) }), _jsx("div", { className: "value-spec-editor__date-picker__custom-date__input", children: _jsx(CustomSelectorInput, { placeholder: "Unit", className: "value-spec-editor__date-picker__custom-date__input-dropdown", options: Object.values(CUSTOM_DATE_OPTION_UNIT).map((t) => ({
                        value: t.toString(),
                        label: t.toString(),
                    })), onChange: (val) => {
                        setUnitValue(val.value);
                        changeValue(durationValue, val.value, directionValue, referenceMomentValue);
                    }, value: { value: unitValue, label: unitValue }, darkMode: !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled }) }), _jsx("div", { className: "value-spec-editor__date-picker__custom-date__input", children: _jsx(CustomSelectorInput, { className: "value-spec-editor__date-picker__custom-date__input-dropdown", options: Object.values(CUSTOM_DATE_OPTION_DIRECTION).map((t) => ({
                        value: t.toString(),
                        label: t.toString(),
                    })), onChange: (val) => {
                        setDirectionValue(val.value);
                        changeValue(durationValue, unitValue, val.value, referenceMomentValue);
                    }, value: { value: directionValue, label: directionValue }, darkMode: !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled }) }), _jsx("div", { className: "value-spec-editor__date-picker__custom-date__input", children: _jsx(CustomSelectorInput, { className: "value-spec-editor__date-picker__custom-date__input-dropdown", options: Object.values(CUSTOM_DATE_OPTION_REFERENCE_MOMENT).map((t) => ({
                        value: t.toString(),
                        label: t.toString(),
                    })), onChange: (val) => {
                        setReferenceMomentValueValue(val.value);
                        changeValue(durationValue, unitValue, directionValue, val.value);
                    }, value: { value: referenceMomentValue, label: referenceMomentValue }, darkMode: !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled }) })] }));
};
const CustomFirstDayOfValueSpecificationEditor = (props) => {
    const { customDateAdjustOptionValue, updateValueSpecification, setDatePickerOption, } = props;
    const applicationStore = useApplicationStore();
    const selectorRef = useRef(null);
    const [unitValue, setUnitValue] = useState(customDateAdjustOptionValue instanceof CustomFirstDayOfOption
        ? customDateAdjustOptionValue.unit
        : null);
    const changeValue = (latestUnitValue) => {
        if (latestUnitValue !== '') {
            const targetUnitValue = Object.values(CUSTOM_DATE_OPTION_REFERENCE_MOMENT).filter((moment) => moment.toString().includes(latestUnitValue));
            const startDayOfDateOption = targetUnitValue.length > 0
                ? new CustomFirstDayOfOption(guaranteeNonNullable(targetUnitValue[0]?.toString()), latestUnitValue)
                : new CustomFirstDayOfOption('', undefined);
            updateValueSpecification(undefined, startDayOfDateOption);
            setDatePickerOption(startDayOfDateOption);
        }
    };
    useEffect(() => {
        selectorRef.current?.focus();
    }, []);
    return (_jsx("div", { className: "value-spec-editor__date-picker__custom-date", children: _jsx("div", { className: "value-spec-editor__date-picker__custom-date__input", children: _jsx(CustomSelectorInput, { inputRef: selectorRef, placeholder: "Choose a unit...", className: "value-spec-editor__date-picker__custom-date__input-dropdown value-spec-editor__date-picker__custom-date__input-dropdown--full", options: Object.values(CUSTOM_DATE_FIRST_DAY_OF_UNIT).map((t) => ({
                    value: t.toString(),
                    label: t.toString(),
                })), onChange: (val) => {
                    if (val) {
                        setUnitValue(val.value);
                        changeValue(val.value);
                    }
                }, value: unitValue ? { value: unitValue, label: unitValue } : null, darkMode: !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled }) }) }));
};
const CustomPreviousDayOfWeekValueSpecificationEditor = (props) => {
    const { customDateAdjustOptionValue, updateValueSpecification, setDatePickerOption, } = props;
    const applicationStore = useApplicationStore();
    const selectorRef = useRef(null);
    const [dayOfWeekValue, setDayOfWeekValue] = useState(customDateAdjustOptionValue instanceof CustomPreviousDayOfWeekOption
        ? customDateAdjustOptionValue.day
        : null);
    const changeValue = (latestDurationUnitValue) => {
        if (latestDurationUnitValue !== '') {
            const previousDayOfWeekDateOption = new CustomPreviousDayOfWeekOption(`Previous ${latestDurationUnitValue}`, latestDurationUnitValue);
            updateValueSpecification(undefined, previousDayOfWeekDateOption);
            setDatePickerOption(previousDayOfWeekDateOption);
        }
    };
    useEffect(() => {
        selectorRef.current?.focus();
    }, []);
    return (_jsx("div", { className: "value-spec-editor__date-picker__custom-date", children: _jsx("div", { className: "value-spec-editor__date-picker__custom-date__input", children: _jsx(CustomSelectorInput, { inputRef: selectorRef, placeholder: "Choose a day...", className: "value-spec-editor__date-picker__custom-date__input-dropdown value-spec-editor__date-picker__custom-date__input-dropdown--full", options: Object.values(CUSTOM_DATE_DAY_OF_WEEK).map((t) => ({
                    value: t.toString(),
                    label: t.toString(),
                })), onChange: (val) => {
                    if (val) {
                        setDayOfWeekValue(val.value);
                        changeValue(val.value);
                    }
                }, value: dayOfWeekValue
                    ? { value: dayOfWeekValue, label: dayOfWeekValue }
                    : null, darkMode: !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled }) }) }));
};
export const CustomDatePicker = (props) => {
    const { valueSpecification, valueSelector, updateValueSpecification, hasError, typeCheckOption, displayAsEditableValue, handleBlur, readOnly, } = props;
    const applicationStore = useApplicationStore();
    // For some cases where types need to be matched strictly.
    // Some options need to be filtered out for DateTime.
    const targetDateOptionsEnum = typeCheckOption.match
        ? Object.values([
            CUSTOM_DATE_PICKER_OPTION.ABSOLUTE_TIME,
            CUSTOM_DATE_PICKER_OPTION.NOW,
        ])
        : Object.values(CUSTOM_DATE_PICKER_OPTION);
    const [datePickerOption, setDatePickerOption] = useState(buildDatePickerOption(valueSpecification, applicationStore));
    const [anchorEl, setAnchorEl] = useState(null);
    const openCustomDatePickerPopover = (event) => {
        setAnchorEl(event.currentTarget);
    };
    const handleEnter = () => {
        setDatePickerOption(buildDatePickerOption(valueSpecification, applicationStore));
    };
    const closeCustomDatePickerPopover = () => {
        setDatePickerOption(buildDatePickerOption(valueSpecification, applicationStore));
        setAnchorEl(null);
        handleBlur?.();
    };
    const handleDatePickerOptionChange = (event) => {
        const chosenDatePickerOption = new DatePickerOption(event.target.value, event.target.value);
        if (CUSTOM_DATE_PICKER_OPTION.LATEST_DATE === chosenDatePickerOption.value) {
            updateValueSpecification(undefined, event.target.value, {
                primitiveTypeEnum: PRIMITIVE_TYPE.LATESTDATE,
            });
        }
        else if (
        // Elements in this list will trigger children date components
        ![
            CUSTOM_DATE_PICKER_OPTION.ABSOLUTE_DATE,
            CUSTOM_DATE_PICKER_OPTION.ABSOLUTE_TIME,
            CUSTOM_DATE_PICKER_OPTION.CUSTOM_DATE,
            CUSTOM_DATE_PICKER_OPTION.FIRST_DAY_OF,
            CUSTOM_DATE_PICKER_OPTION.PREVIOUS_DAY_OF_WEEK,
        ].includes(chosenDatePickerOption.value)) {
            const theReservedCustomDateOption = reservedCustomDateOptions.filter((d) => d.value === chosenDatePickerOption.value);
            if (theReservedCustomDateOption.length > 0) {
                updateValueSpecification(undefined, guaranteeNonNullable(theReservedCustomDateOption[0]));
            }
            else {
                updateValueSpecification(undefined, chosenDatePickerOption);
            }
        }
        setDatePickerOption(chosenDatePickerOption);
    };
    const renderChildrenDateComponents = () => {
        switch (datePickerOption.value) {
            case CUSTOM_DATE_PICKER_OPTION.ABSOLUTE_DATE:
                return (_jsx(AbsoluteDateValueSpecificationEditor, { valueSpecification: valueSpecification, valueSelector: valueSelector, updateValueSpecification: updateValueSpecification, setDatePickerOption: setDatePickerOption }));
            case CUSTOM_DATE_PICKER_OPTION.ABSOLUTE_TIME:
                return (_jsx(AbsoluteTimeValueSpecificationEditor, { valueSpecification: valueSpecification, valueSelector: valueSelector, updateValueSpecification: updateValueSpecification, setDatePickerOption: setDatePickerOption }));
            case CUSTOM_DATE_PICKER_OPTION.CUSTOM_DATE:
                return (_jsx(CustomDateInstanceValueEditor, { customDateOptionValue: buildCustomDateOption(valueSpecification, applicationStore), updateValueSpecification: updateValueSpecification, setDatePickerOption: setDatePickerOption }));
            case CUSTOM_DATE_PICKER_OPTION.FIRST_DAY_OF:
                return (_jsx(CustomFirstDayOfValueSpecificationEditor, { customDateAdjustOptionValue: buildDatePickerOption(valueSpecification, applicationStore), updateValueSpecification: updateValueSpecification, setDatePickerOption: setDatePickerOption }));
            case CUSTOM_DATE_PICKER_OPTION.PREVIOUS_DAY_OF_WEEK:
                return (_jsx(CustomPreviousDayOfWeekValueSpecificationEditor, { customDateAdjustOptionValue: buildDatePickerOption(valueSpecification, applicationStore), updateValueSpecification: updateValueSpecification, setDatePickerOption: setDatePickerOption }));
            default:
                return null;
        }
    };
    // make sure the date picker label is updated when the value is reset or changed somehow
    useEffect(() => {
        setDatePickerOption(buildDatePickerOption(valueSpecification, applicationStore));
    }, [applicationStore, valueSpecification]);
    return (_jsxs(_Fragment, { children: [displayAsEditableValue ? (_jsx("span", { className: clsx('value-spec-editor__date-picker__editable__display--content editable-value', {
                    'value-spec-editor__date-picker__editable__display--content--error': hasError,
                }), title: readOnly ? '' : 'Click to edit and pick from more date options', onClick: readOnly ? () => { } : openCustomDatePickerPopover, style: { cursor: readOnly ? 'not-allowed' : '' }, children: datePickerOption.label ? (`"${datePickerOption.label}"`) : (_jsx(_Fragment, { children: "\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0" })) })) : (_jsx("button", { className: clsx('value-spec-editor__date-picker__trigger', {
                    'value-spec-editor__date-picker__trigger--error': hasError,
                }), title: readOnly ? '' : 'Click to edit and pick from more date options', onClick: openCustomDatePickerPopover, disabled: readOnly, children: datePickerOption.label || 'Select value' })), _jsxs(BasePopover, { open: Boolean(anchorEl), slotProps: {
                    transition: {
                        onEnter: handleEnter,
                    },
                }, anchorEl: anchorEl, onClose: closeCustomDatePickerPopover, anchorOrigin: {
                    vertical: displayAsEditableValue ? 20 : 'bottom',
                    horizontal: displayAsEditableValue ? 50 : 'center',
                }, transformOrigin: {
                    vertical: 'top',
                    horizontal: 'center',
                }, children: [_jsx(BaseRadioGroup, { className: "value-spec-editor__date-picker__options", value: datePickerOption.value, onChange: handleDatePickerOptionChange, row: true, options: targetDateOptionsEnum, size: 2 }), renderChildrenDateComponents()] })] }));
};
//# sourceMappingURL=CustomDatePicker.js.map