import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { getElementId, getItemsMap, setAllItemsState, setItemState } from './utils';
export function useListNavigation({
  adapter,
  list,
  isDisabled = false,
  container,
  listId
}) {
  const [items, setItems] = useState(adapter.getFocusableItems(list.map(adapter.getItem)));
  const itemsMap = useMemo(() => getItemsMap(items), [items]);
  const refs = useRef(new Map());
  const focused = useMemo(() => items.find(n => n.isFocused) ?? null, [items]);
  const [lastFocused, setLastFocused] = useState(focused?.id ?? null);
  const [lastFocusedIsPresent, setLastFocusedIsPresent] = useState(!!focused?.id);
  const selected = useMemo(() => items.filter(i => !!i.isSelected).map(({
    id
  }) => id), [items]);
  const setFocused = useCallback(id => {
    setLastFocused(id);
    setLastFocusedIsPresent(true);
    setItems(state => {
      const unselectedState = setAllItemsState({
        isFocused: false
      }, state);
      return setItemState(id, {
        isFocused: true
      }, unselectedState);
    });
  }, []);
  const toggleSelected = useCallback(id => {
    setItems(state => {
      const item = itemsMap.get(id);
      return setItemState(id, {
        isSelected: !item?.isSelected
      }, state);
    });
  }, [itemsMap]);
  const setBlurred = useCallback(id => {
    setItems(state => {
      return setItemState(id, {
        isFocused: false
      }, state);
    });
  }, []);
  useEffect(() => {
    const nextItems = adapter.getFocusableItems(list.map(adapter.getItem));
    const nextItemsWithFocus = focused?.id ? setItemState(focused.id, {
      isFocused: true
    }, nextItems) : nextItems;
    const nextHasLastFocused = nextItems.find(({
      id
    }) => id === lastFocused);
    setItems(nextItemsWithFocus);
    if (lastFocused && !nextHasLastFocused && lastFocusedIsPresent) {
      setLastFocusedIsPresent(false);
    }
    if (lastFocused && nextHasLastFocused && !lastFocusedIsPresent) {
      setLastFocusedIsPresent(true);
    }
  }, [list, adapter.getFocusableItems, adapter.getItem]);
  useLayoutEffect(() => {
    if (container?.current) {
      if (focused?.id) {
        container.current.setAttribute('aria-activedescendant', getElementId(listId, focused.id));
      } else {
        container.current.removeAttribute('aria-activedescendant');
      }
    }
  }, [focused]);
  const context = {
    items,
    setItems,
    itemsMap,
    isDisabled,
    focused,
    lastFocused,
    lastFocusedIsPresent,
    selected,
    refs,
    toggleSelected,
    setFocused,
    setBlurred,
    listId
  };
  return useMemo(() => context, Object.values(context));
}