import { useEffect, useState } from "react";
import { useEventCallback } from "../../../utils/hooks/index.js";
import { focusInitialTableTarget } from "../helpers/table-cell.js";
import { focusCell, focusCellAndUpdateTabIndex } from "../helpers/table-focus.js";
import { findFirstCell, findFirstCellInRow, findLastCell, findLastCellInRow, findNextFocusableCell, } from "../helpers/table-grid-nav.js";
import { getNavigationAction, shouldBlockNavigation, } from "../helpers/table-keyboard.js";
import { useGridCache } from "./useGridCache.js";
function useTableKeyboardNav({ enabled }) {
    const [tableRef, setTableRef] = useState(null);
    const { getTableGrid, activeCell, setActiveCell } = useGridCache(tableRef, enabled);
    /**
     * Executes a navigation action and returns the target cell.
     */
    const executeNavigationAction = useEventCallback((action) => {
        if (!tableRef) {
            return null;
        }
        let currentCell = activeCell;
        currentCell !== null && currentCell !== void 0 ? currentCell : (currentCell = focusInitialTableTarget(tableRef));
        if (!currentCell) {
            return null;
        }
        const { grid, positions } = getTableGrid(tableRef);
        const currentPos = positions.get(currentCell);
        let nextCell = null;
        switch (action.type) {
            case "delta": {
                if (!currentPos) {
                    return null;
                }
                nextCell = findNextFocusableCell(grid, currentPos, action.delta, currentCell);
                break;
            }
            case "home": {
                if (!currentPos) {
                    return null;
                }
                nextCell = findFirstCellInRow(grid, currentPos.y);
                break;
            }
            case "end": {
                if (!currentPos) {
                    return null;
                }
                nextCell = findLastCellInRow(grid, currentPos.y);
                break;
            }
            case "tableStart": {
                nextCell = findFirstCell(grid);
                break;
            }
            case "tableEnd": {
                nextCell = findLastCell(grid);
                break;
            }
        }
        if (!nextCell || nextCell === currentCell) {
            return null;
        }
        return focusCellAndUpdateTabIndex(nextCell, currentCell);
    });
    /**
     * Handles keyboard navigation with arrow keys, Home/End, and PageUp/PageDown.
     * Checks if navigation should be blocked based on current focus context.
     */
    const handleTableKeyDown = useEventCallback((event) => {
        const action = getNavigationAction(event);
        if (!action) {
            return;
        }
        if (shouldBlockNavigation(event)) {
            return;
        }
        event.preventDefault();
        const newCell = executeNavigationAction(action);
        newCell && setActiveCell(newCell);
    });
    /**
     * When focus is moved to elements inside a cell like inputs, checkbox etc
     * we want to update the active cell to the parent td/th, so that keyboard navigation continues to work as expected from there.
     * Make sure td/th elements have tabIndex={-1} so they can receive focus on click
     */
    const handleTableFocusIn = useEventCallback((event) => {
        var _a;
        const target = event.target;
        if (tableRef && target === tableRef) {
            if (activeCell) {
                focusCell(activeCell);
                return;
            }
            focusInitialTableTarget(tableRef);
            return;
        }
        const newCell = (_a = target === null || target === void 0 ? void 0 : target.closest("td, th")) !== null && _a !== void 0 ? _a : null;
        if (!newCell || newCell === activeCell) {
            return;
        }
        const updatedCell = focusCellAndUpdateTabIndex(newCell, activeCell, {
            shouldFocus: false,
        });
        if (updatedCell) {
            setActiveCell(updatedCell);
        }
    });
    /**
     * Attach event listeners for keyboard navigation and focus management.
     */
    useEffect(() => {
        if (!tableRef || !enabled) {
            return;
        }
        tableRef.addEventListener("keydown", handleTableKeyDown);
        tableRef.addEventListener("focusin", handleTableFocusIn);
        return () => {
            tableRef.removeEventListener("keydown", handleTableKeyDown);
            tableRef.removeEventListener("focusin", handleTableFocusIn);
        };
    }, [tableRef, handleTableKeyDown, handleTableFocusIn, enabled]);
    return {
        /* Table should only have tabIndex until the focus is moved inside and is enabled */
        tabIndex: enabled ? 0 : undefined,
        setTableRef,
    };
}
export { useTableKeyboardNav };
//# sourceMappingURL=useTableKeyboardNav.js.map