import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
// (C) 2021-2026 GoodData Corporation
import { useCallback, useEffect, useMemo, useRef, useState, } from "react";
import cx from "classnames";
import { useIntl } from "react-intl";
import { Button, ItemsWrapper, Overlay, SingleSelectListItem, UiFocusManager, UiTooltip, getFocusableElements, isActionKey, makeMenuKeyboardNavigation, useId, useIdPrefixed, } from "@gooddata/sdk-ui-kit";
import { DEFAULT_MENU_BUTTON_ID } from "../../../_staging/accessibility/elementId.js";
import { useDashboardSelector } from "../../../model/react/DashboardStoreProvider.js";
import { selectDashboardDensity } from "../../../model/store/ui/uiSelectors.js";
import { DefaultSubmenuHeader } from "./DefaultSubmenuHeader.js";
const overlayAlignPoints = [{ align: "br tr" }];
/**
 * @alpha
 */
export function DefaultMenuButton({ menuItems }) {
    const [isOpen, setIsOpen] = useState(false);
    const [autofocusSubmenu, setAutofocusSubmenu] = useState(false);
    const intl = useIntl();
    const tooltipText = intl.formatMessage({ id: "controlButtons.options.tooltip" });
    const backLabel = intl.formatMessage({ id: "controlButtons.options.back" });
    const closeLabel = intl.formatMessage({ id: "controlButtons.options.closeMenu" });
    const menuWrapperRef = useRef(null);
    const [parentItemId, setParentItemId] = useState(null);
    const menuItemRefs = useRef(new Map());
    const density = useDashboardSelector(selectDashboardDensity);
    const setMenuItemRef = useCallback((itemId) => (element) => {
        if (element) {
            menuItemRefs.current.set(itemId, element);
        }
        else {
            menuItemRefs.current.delete(itemId);
        }
    }, []);
    // generate unique IDs for accessibility and dropdown positioning
    const id = useId();
    const menuId = `menu-${id}`;
    const dropdownAnchorClassName = `dash-header-options-anchor-${id}`;
    const onMenuButtonClick = useCallback(() => {
        setIsOpen((prevIsOpen) => !prevIsOpen);
        setSelectedMenuItem(null);
    }, []);
    const onClose = useCallback(() => {
        setIsOpen(false);
        setSelectedMenuItem(null);
        setParentItemId(null);
        setAutofocusSubmenu(false);
    }, []);
    const openSubmenu = useCallback((menuItem) => {
        setAutofocusSubmenu(true);
        setParentItemId(menuItem.itemId);
        setSelectedMenuItem(menuItem);
    }, []);
    const closeSubmenu = useCallback(() => {
        //parentItemId is set to null later in effect focusing parent item
        setSelectedMenuItem(null);
        setAutofocusSubmenu(true);
    }, []);
    const [selectedMenuItem, setSelectedMenuItem] = useState(null);
    const visibleMenuItems = useMemo(() => (selectedMenuItem?.items ?? menuItems).filter((item) => item.visible !== false), [menuItems, selectedMenuItem]);
    const menuKeyboardNavigationHandler = makeMenuKeyboardNavigation({
        onFocusFirst: () => {
            if (menuWrapperRef.current) {
                const { firstElement } = getFocusableElements(menuWrapperRef.current);
                firstElement?.focus();
            }
        },
        onFocusNext: () => {
            const elements = Array.from(menuItemRefs.current.values());
            const currentIndex = elements.indexOf(document.activeElement);
            const nextElement = currentIndex === elements.length - 1 ? elements[0] : elements[currentIndex + 1];
            nextElement?.focus();
        },
        onFocusPrevious: () => {
            const elements = Array.from(menuItemRefs.current.values());
            const currentIndex = elements.indexOf(document.activeElement);
            const previousElement = currentIndex <= 0 ? elements[elements.length - 1] : elements[currentIndex - 1];
            previousElement?.focus();
        },
        onClose,
        onLeaveLevel(event) {
            const [_itemId, targetItem] = Array.from(menuItemRefs.current.entries()).find(([_, element]) => element === event.target) ||
                [];
            if (targetItem?.role === "menuitem" && parentItemId) {
                closeSubmenu();
            }
        },
        onEnterLevel(event) {
            const [itemId] = Array.from(menuItemRefs.current.entries()).find(([_, element]) => element === event.target) ||
                [];
            const menuItem = visibleMenuItems.find((item) => item.itemId === itemId);
            if (menuItem?.type === "menu") {
                openSubmenu(menuItem);
            }
        },
        onUnhandledKeyDown(event) {
            if (isActionKey(event)) {
                //onSelect by keyboard is handled by the menu item itself
                return;
            }
            event.stopPropagation();
            event.preventDefault();
            if (!selectedMenuItem || event.key !== "Tab" || !menuWrapperRef.current) {
                return;
            }
            const { focusableElements } = getFocusableElements(menuWrapperRef.current);
            let currentIndex = Array.from(focusableElements).indexOf(document.activeElement);
            let nextElement;
            const isMenuItemExceptTheFirstOne = (element) => element.getAttribute("role") === "menuitem" &&
                element !== Array.from(menuItemRefs.current.values())[0];
            const getNextElementIndex = (currentIndex, isShiftKey) => {
                if (isShiftKey) {
                    return currentIndex <= 0 ? focusableElements.length - 1 : currentIndex - 1;
                }
                return (currentIndex + 1) % focusableElements.length;
            };
            do {
                currentIndex = getNextElementIndex(currentIndex, event.shiftKey);
                nextElement = focusableElements[currentIndex];
            } while (isMenuItemExceptTheFirstOne(nextElement));
            nextElement?.focus();
        },
    });
    useEffect(() => {
        if (autofocusSubmenu && selectedMenuItem) {
            const firstElement = Array.from(menuItemRefs.current.values())[0];
            firstElement?.focus();
            setAutofocusSubmenu(false);
        }
        if (autofocusSubmenu && !selectedMenuItem && parentItemId) {
            const element = menuItemRefs.current.get(parentItemId);
            if (element) {
                element.focus();
            }
            setAutofocusSubmenu(false);
            setParentItemId(null);
        }
    }, [selectedMenuItem, parentItemId, menuItemRefs, autofocusSubmenu]);
    if (!visibleMenuItems.length) {
        return null;
    }
    const renderMenuItems = () => {
        return (_jsx(Overlay, { alignTo: `.${dropdownAnchorClassName}`, alignPoints: overlayAlignPoints, className: "gd-header-menu-overlay", closeOnMouseDrag: true, closeOnOutsideClick: true, onClose: onMenuButtonClick, children: _jsx(UiFocusManager, { enableAutofocus: true, enableFocusTrap: true, enableReturnFocusOnUnmount: true, children: _jsx("div", { onKeyDown: menuKeyboardNavigationHandler, children: _jsxs(ItemsWrapper, { smallItemsSpacing: true, className: "gd-menu", wrapperRef: menuWrapperRef, children: [selectedMenuItem ? (_jsx(DefaultSubmenuHeader, { title: selectedMenuItem.itemName, backLabel: backLabel, closeLabel: closeLabel, onClose: onClose, onGoBack: () => {
                                    setAutofocusSubmenu(true);
                                    setSelectedMenuItem(null);
                                } })) : null, _jsx("div", { role: "menu", id: menuId, "aria-labelledby": DEFAULT_MENU_BUTTON_ID, children: visibleMenuItems.map((menuItem) => {
                                    return (_jsx(MenuItem, { menuItem: menuItem, selectedMenuItem: selectedMenuItem, setMenuItemRef: setMenuItemRef, setSelectedMenuItem: setSelectedMenuItem, setParentItemId: setParentItemId, setAutofocusSubmenu: setAutofocusSubmenu, setIsOpen: setIsOpen }, menuItem.itemId));
                                }) })
                        ] }) }) }) }, "topBarMenuButton"));
    };
    return (_jsxs(_Fragment, { children: [
            _jsx(UiTooltip, { arrowPlacement: "top-end", content: tooltipText, anchor: _jsx(Button, { onClick: onMenuButtonClick, value: "\u22EF", id: DEFAULT_MENU_BUTTON_ID, className: cx("gd-button-primary dash-header-options-button s-header-options-button gd-button", dropdownAnchorClassName, {
                        "gd-button-small": density === "compact",
                    }), accessibilityConfig: {
                        ariaLabel: tooltipText,
                        role: "button",
                        isExpanded: isOpen,
                        popupId: menuId,
                    } }), triggerBy: ["hover", "focus"] }), isOpen ? renderMenuItems() : null] }));
}
function MenuItem({ menuItem, selectedMenuItem, setMenuItemRef, setSelectedMenuItem, setParentItemId, setAutofocusSubmenu, setIsOpen, }) {
    const tooltipId = useIdPrefixed(`menu-tooltip-${menuItem.itemId}`);
    const renderWithOptionalTooltip = (menuItem, children) => {
        const selectorClassName = `gd-menu-item-${menuItem.itemId}`;
        const hasTooltip = !!menuItem.tooltip;
        const element = children({
            selectorClassName,
            tooltipId: hasTooltip ? tooltipId : undefined,
        });
        if (!hasTooltip) {
            return element;
        }
        return (_jsx(UiTooltip, { id: tooltipId, triggerBy: ["hover", "focus"], arrowPlacement: "right", optimalPlacement: true, content: menuItem.tooltip, anchor: element }));
    };
    if (menuItem.type === "separator") {
        return (_jsx(SingleSelectListItem, { type: menuItem.type, className: menuItem.className, accessibilityConfig: {
                role: "separator",
            } }, menuItem.itemId));
    }
    if (menuItem.type === "header") {
        return (_jsx(SingleSelectListItem, { ref: setMenuItemRef(menuItem.itemId), type: menuItem.type, title: menuItem.itemName, className: menuItem.className, accessibilityConfig: {
                role: "presentation",
            } }, menuItem.itemId));
    }
    if (menuItem.type === "menu") {
        return renderWithOptionalTooltip(menuItem, ({ selectorClassName, tooltipId }) => (_jsx(SingleSelectListItem, { ref: setMenuItemRef(menuItem.itemId), className: cx("gd-menu-item", menuItem.className, `s-${menuItem.itemId}`, {
                [selectorClassName]: menuItem.tooltip,
                "is-disabled": menuItem.disabled,
            }), title: menuItem.itemName, icon: menuItem.icon, isMenu: true, onClick: menuItem.disabled
                ? undefined
                : () => {
                    setAutofocusSubmenu(true);
                    setParentItemId(menuItem.itemId);
                    setSelectedMenuItem(menuItem);
                }, elementType: "button", accessibilityConfig: {
                role: "menuitem",
                ariaHasPopup: "menu",
                ariaExpanded: selectedMenuItem?.itemId === menuItem.itemId,
                ariaDisabled: menuItem.disabled,
                ariaDescribedBy: menuItem.disabled ? tooltipId : undefined,
            } }, menuItem.itemId)));
    }
    return renderWithOptionalTooltip(menuItem, ({ selectorClassName, tooltipId }) => (_jsx(SingleSelectListItem, { ref: setMenuItemRef(menuItem.itemId), className: cx("gd-menu-item", menuItem.className, `s-${menuItem.itemId}`, {
            [selectorClassName]: menuItem.tooltip,
            "is-disabled": menuItem.disabled,
        }), title: menuItem.itemName, icon: menuItem.icon, onClick: menuItem.disabled
            ? undefined
            : () => {
                menuItem.onClick?.();
                setIsOpen(false);
                setSelectedMenuItem(null);
            }, elementType: "button", accessibilityConfig: {
            role: "menuitem",
            ariaDisabled: menuItem.disabled,
            ariaHasPopup: menuItem.opensDialog ? "dialog" : undefined,
            ariaDescribedBy: menuItem.disabled ? tooltipId : undefined,
        } }, menuItem.itemId)));
}
//# sourceMappingURL=DefaultMenuButton.js.map