import { jsx as _jsx } from "react/jsx-runtime";
// (C) 2019-2026 GoodData Corporation
import { memo, useCallback, useEffect, useMemo, useRef, useState, } from "react";
import moment from "moment";
import { injectIntl } from "react-intl";
import { IntlWrapper } from "@gooddata/sdk-ui";
import { sanitizeLocaleForMoment } from "@gooddata/util";
import { UiListbox } from "../@ui/UiListbox/UiListbox.js";
import { Dropdown } from "../Dropdown/Dropdown.js";
import { DropdownButton } from "../Dropdown/DropdownButton.js";
import { SingleSelectListItem } from "../List/ListItem.js";
import { HOURS_IN_DAY, TIME_ANCHOR, formatTime, normalizeTime, updateTime } from "./utils/timeUtilities.js";
const DEFAULT_WIDTH = 199;
const MINUTES_IN_HOUR = 60;
const MAX_HEIGHT = 140;
export const WrappedTimepicker = memo(function WrappedTimepicker({ time = new Date(), className = "", ariaLabelledBy, ariaDescribedBy, onChange = () => { }, overlayPositionType, overlayZIndex = 0, skipNormalizeTime = false, timeAnchor = TIME_ANCHOR, timeFormat = undefined, closeOnParentScroll, intl, }) {
    const dropdownRef = useRef(null);
    const updateLocaleForMoment = useCallback(() => {
        moment.locale(sanitizeLocaleForMoment(intl.locale));
    }, [intl.locale]);
    updateLocaleForMoment();
    const initialTime = time || new Date();
    const [dropdownWidth, setDropdownWidth] = useState(DEFAULT_WIDTH);
    const [selectedTime, setSelectedTime] = useState(skipNormalizeTime ? initialTime : normalizeTime(initialTime, undefined, timeAnchor));
    useEffect(() => {
        const updatedTime = time || new Date();
        const newSelectedTime = skipNormalizeTime
            ? updatedTime
            : normalizeTime(updatedTime, undefined, timeAnchor);
        if (newSelectedTime.getTime() !== selectedTime.getTime()) {
            setSelectedTime(newSelectedTime);
        }
    }, [time, skipNormalizeTime, timeAnchor, selectedTime]);
    const updateDropdownWidth = useCallback(() => {
        if (!dropdownRef.current) {
            return;
        }
        const { width } = dropdownRef.current.getBoundingClientRect();
        setDropdownWidth(width);
    }, []);
    useEffect(() => {
        updateDropdownWidth();
    }, [updateDropdownWidth]);
    const getComponentClasses = useCallback(() => {
        return `gd-datepicker ${className} gd-datepicker-input gd-timepicker`;
    }, [className]);
    const getTimeItems = useCallback((selectedTime) => {
        let currentItem;
        const items = [];
        const { h: hours, m: minutes } = selectedTime;
        for (let h = 0; h < HOURS_IN_DAY; h += 1) {
            for (let m = 0; m < MINUTES_IN_HOUR; m += timeAnchor) {
                const item = {
                    h,
                    m,
                    title: formatTime(h, m, timeFormat),
                };
                items.push(item);
                if (h === hours && m === minutes) {
                    currentItem = item;
                }
            }
        }
        return { items, currentItem };
    }, [timeAnchor, timeFormat]);
    const handleTimeChanged = useCallback((newlySelectedTime) => {
        if (!newlySelectedTime) {
            return;
        }
        const { h, m } = newlySelectedTime;
        const newSelectedTime = updateTime(h, m);
        setSelectedTime(newSelectedTime);
        onChange(newSelectedTime);
    }, [onChange]);
    const timeObj = useMemo(() => ({
        h: selectedTime.getHours(),
        m: selectedTime.getMinutes(),
    }), [selectedTime]);
    const { items, currentItem } = useMemo(() => getTimeItems(timeObj), [getTimeItems, timeObj]);
    const accessibilityDropdownButtonLabel = intl.formatMessage({ id: "timePicker.accessibility.label" });
    return (_jsx("div", { className: getComponentClasses(), ref: dropdownRef, children: _jsx(Dropdown, { closeOnParentScroll: closeOnParentScroll, overlayPositionType: overlayPositionType, alignPoints: [
                {
                    align: "bl tl",
                },
                {
                    align: "tl bl",
                },
            ], autofocusOnOpen: true, renderButton: ({ openDropdown, isOpen, dropdownId, buttonRef }) => (_jsx(DropdownButton, { accessibilityConfig: {
                    ariaLabelledBy,
                    ariaDescribedBy,
                    ariaLabel: accessibilityDropdownButtonLabel,
                    popupType: "listbox",
                }, value: formatTime(timeObj.h, timeObj.m, timeFormat), isOpen: isOpen, dropdownId: dropdownId, onClick: openDropdown, iconLeft: "gd-icon-timer", buttonRef: buttonRef })), renderBody: useCallback(({ closeDropdown, ariaAttributes }) => {
                const listboxItems = items.map((item) => ({
                    type: "interactive",
                    id: `${item.h}-${item.m}`,
                    stringTitle: item.title,
                    data: item,
                }));
                const handleKeyDown = (e) => {
                    if (e.key !== "Tab") {
                        return;
                    }
                    closeDropdown();
                };
                return (_jsx(UiListbox, { shouldKeyboardActionStopPropagation: true, shouldKeyboardActionPreventDefault: true, dataTestId: "s-timepicker-list", items: listboxItems, maxWidth: dropdownWidth, maxHeight: MAX_HEIGHT, selectedItemId: currentItem ? `${currentItem.h}-${currentItem.m}` : undefined, onSelect: (item) => {
                        handleTimeChanged(item.data);
                    }, onClose: closeDropdown, onUnhandledKeyDown: handleKeyDown, ariaAttributes: ariaAttributes, InteractiveItemComponent: ({ item, isSelected, onSelect, isFocused }) => {
                        return (_jsx(SingleSelectListItem, { title: item.stringTitle, isSelected: isSelected, isFocused: isFocused, onClick: onSelect, className: "gd-timepicker-list-item" }));
                    } }));
            }, [items, handleTimeChanged, currentItem, dropdownWidth]), overlayZIndex: overlayZIndex }) }));
});
const TimePickerWithIntl = injectIntl(WrappedTimepicker);
/**
 * @internal
 */
export const Timepicker = memo(function Timepicker(props) {
    return (_jsx(IntlWrapper, { locale: props.locale, children: _jsx(TimePickerWithIntl, { ...props }) }));
});
