var _globalObject$documen2;
import ReactDOM from 'react-dom';
import debounce from 'lodash.debounce';
import { globalObject } from '@skbkontur/global-object';
import { PORTAL_INLET_ATTR, PORTAL_OUTLET_ATTR } from "../../internal/RenderContainer";
import { isInstanceOf } from "../isInstanceOf";
import { isFirefox } from "../client";
var handlers = [];
function addHandleEvent() {
  var _globalObject$documen;
  /**
   * Firefox do not supports 'focusin' event.
   * Focus events bubbles multiple time
   * without possibilty to cancell bubbling.
   * Using debounce to capture only first focus event
   * Mozilla Firefix
   *   ¯\_(ツ)_/¯
   */
  (_globalObject$documen = globalObject.document) == null || _globalObject$documen.body.addEventListener(isFirefox ? 'focus' : 'focusin', isFirefox ? debounce(handleNativeFocus, 0, {
    leading: true,
    trailing: false
  }) : handleNativeFocus, {
    capture: true
  });
}
if (((_globalObject$documen2 = globalObject.document) == null ? void 0 : _globalObject$documen2.readyState) === 'complete') {
  addHandleEvent();
} else {
  globalObject.addEventListener == null || globalObject.addEventListener('load', addHandleEvent);
}
function handleNativeFocus(event) {
  // FIXME: not safe casting
  var target = event.target || event.srcElement;
  handlers.forEach(function (handler) {
    var elements = handler.elements;
    if (typeof elements === 'function') {
      elements = elements();
    }
    if (elements.some(containsTargetOrRenderContainer(target))) {
      return;
    }
    ReactDOM.unstable_batchedUpdates(function () {
      return handler.callback(event);
    });
  });
}
export function containsTargetOrRenderContainer(target) {
  return function (element) {
    if (!element) {
      return false;
    }
    if (element.contains(target)) {
      return true;
    }
    var container = findRenderContainer(target, element);
    return !!container && element.contains(container);
  };
}

/**
 * Searches RenderContainer placed in "rootNode" for "node"
 */
export function findRenderContainer(node, rootNode, container) {
  var _globalObject$documen3, _globalObject$documen4;
  var currentNode = node.parentNode;
  if (!currentNode || node === rootNode || currentNode === rootNode || currentNode === ((_globalObject$documen3 = globalObject.document) == null ? void 0 : _globalObject$documen3.body) || currentNode === ((_globalObject$documen4 = globalObject.document) == null ? void 0 : _globalObject$documen4.documentElement) || !isInstanceOf(currentNode, globalObject.Element)) {
    return container ? container : null;
  }
  var newContainerId = currentNode.getAttribute(PORTAL_OUTLET_ATTR);
  if (newContainerId) {
    var _globalObject$documen5;
    var nextNode = (_globalObject$documen5 = globalObject.document) == null ? void 0 : _globalObject$documen5.querySelector("[" + PORTAL_INLET_ATTR + "~=\"" + newContainerId + "\"]");
    if (!nextNode) {
      throw Error("Origin node for render container was not found");
    }
    return findRenderContainer(nextNode, rootNode, nextNode);
  }
  return findRenderContainer(currentNode, rootNode, container);
}
export function listen(elements, callback) {
  var handler = {
    elements: elements,
    callback: callback
  };
  handlers.push(handler);
  return {
    remove: function remove() {
      var index = handlers.indexOf(handler);
      if (index > -1) {
        handlers.splice(index, 1);
      }
    }
  };
}