"use strict";var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;exports.__esModule = true;exports.containsTargetOrRenderContainer = containsTargetOrRenderContainer;exports.findRenderContainer = findRenderContainer;exports.listen = listen;var _reactDom = _interopRequireDefault(require("react-dom"));
var _lodash = _interopRequireDefault(require("lodash.debounce"));
var _globalObject = require("@skbkontur/global-object");

var _RenderContainer = require("../internal/RenderContainer");

var _isInstanceOf = require("./isInstanceOf");
var _client = require("./client");var _globalObject$documen2;






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.globalObject.document) == null || _globalObject$documen.body.addEventListener(
    _client.isFirefox ? 'focus' : 'focusin',
    _client.isFirefox ? (0, _lodash.default)(handleNativeFocus, 0, { leading: true, trailing: false }) : handleNativeFocus,
    { capture: true }
  );
}

if (((_globalObject$documen2 = _globalObject.globalObject.document) == null ? void 0 : _globalObject$documen2.readyState) === 'complete') {
  addHandleEvent();
} else {
  _globalObject.globalObject.addEventListener == null || _globalObject.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.default.unstable_batchedUpdates(function () {return handler.callback(event);});
  });
}

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"
 */
function findRenderContainer(node, rootNode, container) {var _globalObject$documen3, _globalObject$documen4;
  var currentNode = node.parentNode;
  if (
  !currentNode ||
  node === rootNode ||
  currentNode === rootNode ||
  currentNode === ((_globalObject$documen3 = _globalObject.globalObject.document) == null ? void 0 : _globalObject$documen3.body) ||
  currentNode === ((_globalObject$documen4 = _globalObject.globalObject.document) == null ? void 0 : _globalObject$documen4.documentElement) ||
  !(0, _isInstanceOf.isInstanceOf)(currentNode, _globalObject.globalObject.Element))
  {
    return container ? container : null;
  }

  var newContainerId = currentNode.getAttribute(_RenderContainer.PORTAL_OUTLET_ATTR);
  if (newContainerId) {var _globalObject$documen5;
    var nextNode = (_globalObject$documen5 = _globalObject.globalObject.document) == null ? void 0 : _globalObject$documen5.querySelector("[" + _RenderContainer.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);
}

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);
      }
    }
  };
}