/**
 * @license MIT
 * author: Cube Dev Team
 * @cube-dev/ui-kit v0.0.0-canary-9f08182
 * Released under the MIT license.
 */

import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Pressable } from '@react-aria/interactions';
import { useEffect, useMemo, useRef, useState, } from 'react';
import { VisuallyHidden } from 'react-aria';
import { useEvent } from '../../_internal/index.js';
import { generateRandomId } from '../../utils/random.js';
import { mergeProps } from '../../utils/react/index.js';
import { useEventBus } from '../../utils/react/useEventBus.js';
import { MenuTrigger } from './Menu/index.js';
/**
 * Generic hook to manage an anchored menu component.
 *
 * @param Component - A React component that represents the menu content (Menu or CommandMenu).
 * @param defaultTriggerProps - Default props to pass to the MenuTrigger.
 * @param defaultMenuProps - Default props to pass to the Menu component.
 * @returns An object with `anchorRef` to position the menu, `open` function to open the menu with provided props, `close` function to close the menu, and `rendered` JSX element to include in your component tree.
 */
export function useAnchoredMenu(Component, defaultTriggerProps, defaultMenuProps) {
    const [isOpen, setIsOpen] = useState(false);
    const [componentProps, setComponentProps] = useState(null);
    const [triggerProps, setTriggerProps] = useState(null);
    const anchorRef = useRef(null);
    const setupRef = useRef(false);
    useEffect(() => {
        const el = anchorRef.current;
        if (el) {
            el.dataset.popoverTrigger = '';
            return () => {
                delete el.dataset.popoverTrigger;
            };
        }
    }, []);
    // Generate a unique ID for this menu instance
    const menuId = useMemo(() => generateRandomId(), []);
    // Get event bus for menu synchronization
    const { emit, on } = useEventBus();
    // Listen for other menus opening and close this one if needed
    useEffect(() => {
        const unsubscribe = on('popover:open', (data) => {
            // If another menu is opening and this menu is open, close this one
            if (data.menuId !== menuId && isOpen) {
                setIsOpen(false);
            }
        });
        return unsubscribe;
    }, [on, menuId, isOpen]);
    // Emit event when this menu opens
    useEffect(() => {
        if (isOpen) {
            emit('popover:open', { menuId });
        }
    }, [isOpen, emit, menuId]);
    function setupCheck() {
        if (!setupRef.current) {
            throw new Error('useAnchoredMenu: MenuTrigger must be rendered. Use `rendered` property to include it in your component tree.');
        }
    }
    // 'open' accepts props required by the Component and opens the menu
    const open = useEvent((props = {}, triggerProps) => {
        setupCheck();
        // Merge defaultMenuProps with provided props
        const finalProps = defaultMenuProps
            ? { ...defaultMenuProps, ...props }
            : props;
        setComponentProps(finalProps);
        setTriggerProps(triggerProps ?? null);
        setIsOpen(true);
    });
    const update = useEvent((props, triggerProps) => {
        setupCheck();
        // Merge defaultMenuProps with provided props
        const finalProps = defaultMenuProps
            ? { ...defaultMenuProps, ...props }
            : props;
        setComponentProps(finalProps);
        setTriggerProps(triggerProps ?? null);
    });
    const close = useEvent(() => {
        setIsOpen(false);
    });
    // Render the menu only when componentProps is set
    const renderedMenu = useMemo(() => {
        if (!componentProps)
            return null;
        return (_jsxs(MenuTrigger, { isDummy: true, isOpen: isOpen, targetRef: anchorRef, placement: "bottom start", onOpenChange: setIsOpen, ...mergeProps(defaultTriggerProps, triggerProps || undefined), children: [_jsx(VisuallyHidden, { children: _jsx(Pressable, { children: _jsx("button", { "aria-label": "context-menu" }) }) }), _jsx(Component, { ...componentProps })] }));
    }, [componentProps, triggerProps, isOpen, defaultTriggerProps]);
    return {
        anchorRef,
        open,
        update,
        close,
        isOpen,
        get rendered() {
            setupRef.current = true;
            return renderedMenu;
        },
    };
}

        