import { useCallback, useEffect, useRef } from "react";
import { FocusManager } from "./focusManager";
import { focusSelector, isFocusable, isTabble } from "./tabbable";
import { scopeTab } from "./scopeTab";
// Находим элемент для фокуса
var getFocusElement = function getFocusElement(node, firstFocusSelector) {
    var focusElement = null;
    if (firstFocusSelector) {
        if (typeof firstFocusSelector === 'string') {
            focusElement = node.querySelector(firstFocusSelector);
        } else if (firstFocusSelector.current) {
            focusElement = firstFocusSelector.current;
        }
    }
    if (!focusElement) {
        var children = Array.from(node.querySelectorAll(focusSelector));
        focusElement = children.find(function(el) {
            return isTabble(el);
        }) || null;
    }
    // Если ничего не нашлось, то может ли сама нода быть под фокусом
    if (!focusElement && isFocusable(node)) {
        focusElement = node;
    }
    return focusElement;
};
var processNode = function processNode1(node, firstFocusSelector, ref) {
    if (ref === null || ref === void 0 ? void 0 : ref.current) {
        ref.current.removeEventListener('animationend', function() {
            processNode(node, firstFocusSelector, ref);
        });
    }
    var focusElement = getFocusElement(node, firstFocusSelector);
    if (focusElement) {
        focusElement.focus();
    }
};
var focusManager = new FocusManager();
/**
 *  Захватывает фокус внутри DOM node.
 * */ export var useFocusTrap = function useFocusTrap() {
    var active = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : true, firstFocusSelector = arguments.length > 1 ? arguments[1] : void 0, focusAfterNode = arguments.length > 2 ? arguments[2] : void 0, activeAfterAnimation = arguments.length > 3 ? arguments[3] : void 0;
    var ref = useRef();
    var setRef = useCallback(function(node) {
        if (ref.current) {
            focusManager.teardownScopedFocus();
            focusManager.returnFocus();
        }
        if (active && node) {
            focusManager.setupScopedFocus(node);
            focusManager.markForFocusAfter(focusAfterNode);
            // Delay processing the HTML node by a frame. This ensures focus is assigned correctly.
            setTimeout(function() {
                if ((ref === null || ref === void 0 ? void 0 : ref.current) && node.ownerDocument && activeAfterAnimation) {
                    ref.current.addEventListener('animationend', function() {
                        processNode(node, firstFocusSelector, ref);
                    });
                } else if (node.ownerDocument) {
                    processNode(node, firstFocusSelector);
                }
            });
            ref.current = node;
            return;
        }
        ref.current = null;
    }, [
        active,
        firstFocusSelector
    ]);
    useEffect(function() {
        if (!active) {
            return;
        }
        var handleKeyDown = function handleKeyDown(event) {
            if (event.key === 'Tab' && ref.current) {
                scopeTab(ref.current, event);
            }
        };
        document.addEventListener('keydown', handleKeyDown);
        return function() {
            document.removeEventListener('keydown', handleKeyDown);
        };
    }, [
        active
    ]);
    return setRef;
};
