// Copyright 1999-2023. Plesk International GmbH. All rights reserved.

import { useRef, useMemo, forwardRef } from 'react';
import { createFocusManager, mergeRefs, wrapFunction } from '../utils';
import { isFocusable } from '../Overlay/Focuser';
import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
const canSkip = node => node instanceof HTMLElement && node.dataset && node.dataset.skipAutoFocus;
const createFocusStrategy = checkSkipAutoFocusRef => {
  const elements = [];
  return {
    elements,
    collect(container) {
      let reset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      if (reset) {
        this.elements = [];
      }
      for (let i = 0; i < container.children.length; i++) {
        const element = container.children[i];
        if (checkSkipAutoFocusRef.current) {
          if (canSkip(element)) {
            continue;
          }
        }
        this.elements.push(element);
        this.collect(element);
      }
    },
    getFirst(container) {
      this.collect(container, true);
      return this.elements[0];
    },
    getLast(container) {
      this.collect(container, true);
      return this.elements[this.elements.length - 1];
    },
    getNext(_container, element) {
      if (element) {
        const index = this.elements.indexOf(element);
        if (index !== -1) {
          return this.elements[index + 1];
        }
      }
      return undefined;
    },
    getPrev(_container, element) {
      if (element) {
        const index = this.elements.indexOf(element);
        if (index !== -1) {
          return this.elements[index - 1];
        }
      }
      return undefined;
    }
  };
};
const FocusTrap = (_ref, ref) => {
  let {
    children,
    onFocus,
    ...props
  } = _ref;
  const rootRef = useRef(null);
  const trapBeforeRef = useRef(null);
  const trapAfterRef = useRef(null);
  const checkSkipAutoFocusRef = useRef(false);
  const isFitForFocus = node => {
    if (node === trapBeforeRef.current || node === trapAfterRef.current) {
      return false;
    }
    return isFocusable(node);
  };
  const {
    focusFirst,
    focusLast
  } = useMemo(() => {
    const strategy = createFocusStrategy(checkSkipAutoFocusRef);
    return createFocusManager(rootRef, isFitForFocus, strategy);
  }, []);
  const handleFocus = wrapFunction(onFocus, e => {
    if (!rootRef.current) {
      return;
    }
    switch (true) {
      case e.target === trapBeforeRef.current:
        if (rootRef.current !== e.relatedTarget && e.relatedTarget instanceof HTMLElement && rootRef.current.contains(e.relatedTarget)) {
          focusLast();
        } else {
          focusFirst();
        }
        break;
      case e.target === trapAfterRef.current:
        if (rootRef.current !== e.relatedTarget && e.relatedTarget instanceof HTMLElement && rootRef.current.contains(e.relatedTarget)) {
          focusFirst();
        } else {
          focusLast();
        }
        break;
    }
  });
  return /*#__PURE__*/_jsxs("div", {
    onFocus: handleFocus,
    ref: mergeRefs(rootRef, ref),
    tabIndex: -1,
    ...props,
    children: [/*#__PURE__*/_jsx("div", {
      tabIndex: 0,
      ref: trapBeforeRef
    }), children, /*#__PURE__*/_jsx("div", {
      tabIndex: 0,
      ref: trapAfterRef
    })]
  });
};
FocusTrap.displayName = 'FocusTrap';
export default /*#__PURE__*/forwardRef(FocusTrap);