import * as React from 'react';
import { useButton } from '../../use-button/index.js';
import { mergeProps } from '../../merge-props/index.js';
import { useEventCallback } from '../../utils/useEventCallback.js';
import { useForkRef } from '../../utils/useForkRef.js';
export function useSelectItem(params) {
  const {
    open,
    disabled = false,
    highlighted,
    selected,
    ref: externalRef,
    setOpen,
    typingRef,
    handleSelect,
    selectionRef,
    indexRef,
    setActiveIndex,
    popupRef,
    keyboardActiveRef
  } = params;
  const ref = React.useRef(null);
  const mergedRef = useForkRef(externalRef, ref);
  const {
    getButtonProps,
    buttonRef
  } = useButton({
    disabled,
    focusableWhenDisabled: true,
    buttonRef: mergedRef
  });
  const commitSelection = useEventCallback(event => {
    handleSelect();
    setOpen(false, event);
  });
  const lastKeyRef = React.useRef(null);
  const pointerTypeRef = React.useRef('mouse');
  const prevPopupHeightRef = React.useRef(0);
  const allowFocusSyncRef = React.useRef(true);
  const getItemProps = React.useCallback(externalProps => {
    return mergeProps({
      'aria-disabled': disabled || undefined,
      tabIndex: highlighted ? 0 : -1,
      onFocus() {
        if (allowFocusSyncRef.current) {
          setActiveIndex(indexRef.current);
        }
      },
      onMouseMove() {
        setActiveIndex(indexRef.current);
        if (popupRef.current) {
          prevPopupHeightRef.current = popupRef.current.offsetHeight;
        }
      },
      onMouseLeave(event) {
        const popup = popupRef.current;
        if (!popup || !open || keyboardActiveRef.current) {
          return;
        }
        const targetRect = event.currentTarget.getBoundingClientRect();

        // Safari randomly fires `mouseleave` incorrectly when the item is
        // aligned to the trigger. This is a workaround to prevent the highlight
        // from being removed while the cursor is still within the bounds of the item.
        // https://github.com/mui/base-ui/issues/869
        const isWithinBounds = targetRect.top + 1 <= event.clientY && event.clientY <= targetRect.bottom - 1 && targetRect.left + 1 <= event.clientX && event.clientX <= targetRect.right - 1;
        if (isWithinBounds) {
          return;
        }

        // With `alignItemToTrigger`, avoid re-rendering the root due to `onMouseLeave`
        // firing and causing a performance issue when expanding the popup.
        if (popup.offsetHeight === prevPopupHeightRef.current) {
          // Prevent `onFocus` from causing the highlight to be stuck when quickly moving
          // the mouse out of the popup.
          allowFocusSyncRef.current = false;
          setActiveIndex(null);
          requestAnimationFrame(() => {
            popup.focus({
              preventScroll: true
            });
            allowFocusSyncRef.current = true;
          });
        }
      },
      onTouchStart() {
        selectionRef.current = {
          allowSelectedMouseUp: false,
          allowUnselectedMouseUp: false,
          allowSelect: true
        };
      },
      onKeyDown(event) {
        selectionRef.current.allowSelect = true;
        lastKeyRef.current = event.key;
      },
      onClick(event) {
        if (disabled || lastKeyRef.current === ' ' && typingRef.current || pointerTypeRef.current !== 'touch' && !highlighted) {
          return;
        }
        if (selectionRef.current.allowSelect) {
          lastKeyRef.current = null;
          commitSelection(event.nativeEvent);
        }
      },
      onPointerEnter(event) {
        pointerTypeRef.current = event.pointerType;
      },
      onPointerDown(event) {
        pointerTypeRef.current = event.pointerType;
      },
      onMouseUp(event) {
        if (disabled) {
          return;
        }
        const disallowSelectedMouseUp = !selectionRef.current.allowSelectedMouseUp && selected;
        const disallowUnselectedMouseUp = !selectionRef.current.allowUnselectedMouseUp && !selected;
        if (disallowSelectedMouseUp || disallowUnselectedMouseUp || pointerTypeRef.current !== 'touch' && !highlighted) {
          return;
        }
        if (selectionRef.current.allowSelect || !selected) {
          commitSelection(event.nativeEvent);
        }
        selectionRef.current.allowSelect = true;
      }
    }, externalProps, getButtonProps);
  }, [commitSelection, disabled, getButtonProps, highlighted, indexRef, keyboardActiveRef, open, popupRef, selected, selectionRef, setActiveIndex, typingRef]);
  return React.useMemo(() => ({
    getItemProps,
    rootRef: buttonRef
  }), [getItemProps, buttonRef]);
}