"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useKeyboardControlOnSelect = void 0;
const react_1 = require("react");
const useKeyboardControlOnSelect = ({ defaultOption, options, idName, overlayRef, isEnabled, onSelected, optionRefs, optionContainerRef, }) => {
    const [selectingItem, setSelectingItem] = (0, react_1.useState)(defaultOption);
    const [focusedItem, setFocusedItem] = (0, react_1.useState)(null);
    const [lockHover, setLockHover] = (0, react_1.useState)(false);
    const flattenedOptions = options.reduce((flattenedOptions, optionGroup) => {
        if (optionGroup.options)
            return flattenedOptions.concat(optionGroup.options);
        return flattenedOptions.concat([optionGroup]);
    }, []);
    const _onKeyDown = (0, react_1.useCallback)((e) => {
        switch (e.key) {
            case 'ArrowUp': {
                e.preventDefault();
                setLockHover(true);
                const index = flattenedOptions.findIndex((item) => (selectingItem === null || selectingItem === void 0 ? void 0 : selectingItem[idName]) === item[idName]);
                const newIndex = index - 1 < 0 ? flattenedOptions.length - 1 : index - 1;
                const newSelecting = flattenedOptions[newIndex];
                setSelectingItem(newSelecting);
                scrollIntoSelectingItem(newSelecting);
                break;
            }
            case 'ArrowDown': {
                e.preventDefault();
                setLockHover(true);
                const index = flattenedOptions.findIndex((item) => (selectingItem === null || selectingItem === void 0 ? void 0 : selectingItem[idName]) === item[idName]);
                const newIndex = (index + 1) % flattenedOptions.length;
                const newSelecting = flattenedOptions[newIndex];
                setSelectingItem(newSelecting);
                scrollIntoSelectingItem(newSelecting);
                break;
            }
            case 'Tab':
            case 'Enter': {
                e.preventDefault();
                const selectedItem = selectingItem || flattenedOptions[0];
                if (selectedItem)
                    onSelected(selectedItem);
                break;
            }
            default:
        }
    }, [options, setSelectingItem, selectingItem]);
    const scrollIntoSelectingItem = (selecting, smooth = true) => {
        const optionRef = optionRefs.current[selecting[idName]];
        if (optionContainerRef.current && optionRef) {
            scrollToElm(optionContainerRef.current, optionRef, 0.2, optionContainerRef.current.getBoundingClientRect().height / 2);
        }
    };
    const scrollToElm = (container, elm, duration, offset = 0) => {
        const pos = getRelativePos(elm);
        scrollTo(container, pos.top - offset, duration); // duration in seconds
    };
    const getRelativePos = (elm) => {
        const pPos = elm.parentNode.getBoundingClientRect(), // parent pos
        cPos = elm.getBoundingClientRect(), // target pos
        pos = {};
        (pos.top = cPos.top - pPos.top + elm.parentNode.scrollTop),
            (pos.right = cPos.right - pPos.right),
            (pos.bottom = cPos.bottom - pPos.bottom),
            (pos.left = cPos.left - pPos.left);
        return pos;
    };
    const scrollTo = (element, to, duration, onDone) => {
        let now, elapsed, t;
        const startTime = performance.now(), start = element.scrollTop, change = to - start;
        const animateScroll = () => {
            now = performance.now();
            elapsed = (now - startTime) / 1000;
            t = elapsed / duration;
            element.scrollTop = start + change * easeInOutQuad(t);
            if (t < 1)
                window.requestAnimationFrame(animateScroll);
            else
                onDone && onDone();
        };
        animateScroll();
    };
    const easeInOutQuad = (t) => {
        return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
    };
    (0, react_1.useEffect)(() => setSelectingItem(focusedItem || defaultOption), [defaultOption, focusedItem]);
    (0, react_1.useEffect)(() => {
        if (isEnabled)
            window.addEventListener('keydown', _onKeyDown);
        return () => {
            if (isEnabled)
                window.removeEventListener('keydown', _onKeyDown);
        };
    }, [_onKeyDown, isEnabled]);
    (0, react_1.useEffect)(() => {
        setSelectingItem(flattenedOptions.find((item) => item[idName] === (selectingItem === null || selectingItem === void 0 ? void 0 : selectingItem[idName])));
    }, [options]);
    (0, react_1.useEffect)(() => {
        if (isEnabled && overlayRef && defaultOption) {
            scrollIntoSelectingItem(defaultOption, false);
        }
    }, [isEnabled, defaultOption, overlayRef]);
    const onItemMouseEnter = (item) => {
        if (!lockHover)
            setFocusedItem(item);
    };
    const onItemMouseLeave = () => {
        if (!lockHover)
            setFocusedItem(null);
    };
    const onItemMouseMove = () => setLockHover(false);
    return {
        selectingItem,
        onItemMouseEnter,
        onItemMouseLeave,
        onItemMouseMove,
    };
};
exports.useKeyboardControlOnSelect = useKeyboardControlOnSelect;
//# sourceMappingURL=KeyboardControlOnSelect.js.map