'use client';

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { safePolygon, useClick, useDismiss, useFloatingRootContext, useHover, useInteractions, useListNavigation, useRole, useTypeahead } from '@floating-ui/react';
import { useTransitionStatus } from '../../utils/useTransitionStatus.js';
import { useEventCallback } from '../../utils/useEventCallback.js';
import { useControlled } from '../../utils/useControlled.js';
import { PATIENT_CLICK_THRESHOLD, TYPEAHEAD_RESET_MS } from '../../utils/constants.js';
import { useOpenChangeComplete } from '../../utils/useOpenChangeComplete.js';
import { useScrollLock } from '../../utils/useScrollLock.js';
import { translateOpenChangeReason } from '../../utils/translateOpenChangeReason.js';
const EMPTY_ARRAY = [];
export function useMenuRoot(parameters) {
  const {
    open: openParam,
    defaultOpen,
    onOpenChange,
    onOpenChangeComplete,
    orientation,
    direction,
    disabled,
    nested,
    closeParentOnEsc,
    loop,
    delay,
    openOnHover,
    onTypingChange,
    modal
  } = parameters;
  const [triggerElement, setTriggerElement] = React.useState(null);
  const [positionerElement, setPositionerElementUnwrapped] = React.useState(null);
  const [instantType, setInstantType] = React.useState();
  const [hoverEnabled, setHoverEnabled] = React.useState(true);
  const [activeIndex, setActiveIndex] = React.useState(null);
  const [openReason, setOpenReason] = React.useState(null);
  const [stickIfOpen, setStickIfOpen] = React.useState(true);
  const popupRef = React.useRef(null);
  const positionerRef = React.useRef(null);
  const stickIfOpenTimeoutRef = React.useRef(-1);
  const [open, setOpenUnwrapped] = useControlled({
    controlled: openParam,
    default: defaultOpen,
    name: 'useMenuRoot',
    state: 'open'
  });
  const setPositionerElement = React.useCallback(value => {
    positionerRef.current = value;
    setPositionerElementUnwrapped(value);
  }, []);
  const allowMouseUpTriggerRef = React.useRef(false);
  const {
    mounted,
    setMounted,
    transitionStatus
  } = useTransitionStatus(open);
  useScrollLock(open && modal && openReason !== 'hover', triggerElement);
  const setOpen = useEventCallback((nextOpen, event, reason) => {
    onOpenChange?.(nextOpen, event);
    setOpenUnwrapped(nextOpen);
    if (nextOpen) {
      setOpenReason(reason ?? null);
    }
  });
  if (!open && !hoverEnabled) {
    setHoverEnabled(true);
  }
  const handleUnmount = useEventCallback(() => {
    setMounted(false);
    setOpenReason(null);
    setStickIfOpen(true);
    onOpenChangeComplete?.(false);
  });
  useOpenChangeComplete({
    enabled: !parameters.actionsRef,
    open,
    ref: popupRef,
    onComplete() {
      if (!open) {
        handleUnmount();
      }
    }
  });
  React.useImperativeHandle(parameters.actionsRef, () => ({
    unmount: handleUnmount
  }), [handleUnmount]);
  const clearStickIfOpenTimeout = useEventCallback(() => {
    clearTimeout(stickIfOpenTimeoutRef.current);
  });
  React.useEffect(() => {
    if (!open) {
      clearStickIfOpenTimeout();
    }
  }, [clearStickIfOpenTimeout, open]);
  React.useEffect(() => {
    return clearStickIfOpenTimeout;
  }, [clearStickIfOpenTimeout]);
  const floatingRootContext = useFloatingRootContext({
    elements: {
      reference: triggerElement,
      floating: positionerElement
    },
    open,
    onOpenChange(openValue, eventValue, reasonValue) {
      const isHover = reasonValue === 'hover' || reasonValue === 'safe-polygon';
      const isKeyboardClick = reasonValue === 'click' && eventValue.detail === 0;
      const isDismissClose = !openValue && (reasonValue === 'escape-key' || reasonValue == null);
      function changeState() {
        setOpen(openValue, eventValue, translateOpenChangeReason(reasonValue));
      }
      if (isHover) {
        // Only allow "patient" clicks to close the menu if it's open.
        // If they clicked within 500ms of the menu opening, keep it open.
        clearStickIfOpenTimeout();
        setStickIfOpen(true);
        stickIfOpenTimeoutRef.current = window.setTimeout(() => {
          setStickIfOpen(false);
        }, PATIENT_CLICK_THRESHOLD);
        ReactDOM.flushSync(changeState);
      } else {
        changeState();
      }
      if (isKeyboardClick || isDismissClose) {
        setInstantType(isKeyboardClick ? 'click' : 'dismiss');
      } else {
        setInstantType(undefined);
      }
    }
  });
  const hover = useHover(floatingRootContext, {
    enabled: hoverEnabled && openOnHover && !disabled && openReason !== 'click',
    handleClose: safePolygon({
      blockPointerEvents: true
    }),
    mouseOnly: true,
    move: false,
    delay: {
      open: delay
    }
  });
  const click = useClick(floatingRootContext, {
    enabled: !disabled,
    event: 'mousedown',
    toggle: !openOnHover || !nested,
    ignoreMouse: openOnHover && nested,
    stickIfOpen
  });
  const dismiss = useDismiss(floatingRootContext, {
    bubbles: closeParentOnEsc && nested,
    outsidePressEvent: 'mousedown'
  });
  const role = useRole(floatingRootContext, {
    role: 'menu'
  });
  const itemDomElements = React.useRef([]);
  const itemLabels = React.useRef([]);
  const listNavigation = useListNavigation(floatingRootContext, {
    enabled: !disabled,
    listRef: itemDomElements,
    activeIndex,
    nested,
    loop,
    orientation,
    rtl: direction === 'rtl',
    disabledIndices: EMPTY_ARRAY,
    onNavigate: setActiveIndex
  });
  const typeahead = useTypeahead(floatingRootContext, {
    listRef: itemLabels,
    activeIndex,
    resetMs: TYPEAHEAD_RESET_MS,
    onMatch: index => {
      if (open && index !== activeIndex) {
        setActiveIndex(index);
      }
    },
    onTypingChange
  });
  const {
    getReferenceProps,
    getFloatingProps,
    getItemProps
  } = useInteractions([hover, click, dismiss, role, listNavigation, typeahead]);
  const triggerProps = React.useMemo(() => getReferenceProps({
    onMouseEnter() {
      setHoverEnabled(true);
    }
  }), [getReferenceProps]);
  const popupProps = React.useMemo(() => getFloatingProps({
    onMouseEnter() {
      if (!openOnHover || nested) {
        setHoverEnabled(false);
      }
    },
    onClick() {
      if (openOnHover) {
        setHoverEnabled(false);
      }
    }
  }), [getFloatingProps, openOnHover, nested]);
  const itemProps = React.useMemo(() => getItemProps(), [getItemProps]);
  return React.useMemo(() => ({
    activeIndex,
    allowMouseUpTriggerRef,
    floatingRootContext,
    itemProps,
    popupProps,
    triggerProps,
    itemDomElements,
    itemLabels,
    mounted,
    open,
    popupRef,
    positionerRef,
    setOpen,
    setPositionerElement,
    setTriggerElement,
    transitionStatus,
    openReason,
    instantType,
    onOpenChangeComplete,
    setHoverEnabled
  }), [activeIndex, floatingRootContext, itemProps, popupProps, triggerProps, itemDomElements, itemLabels, mounted, open, positionerRef, setOpen, transitionStatus, setPositionerElement, openReason, instantType, onOpenChangeComplete]);
}