"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.mergeRefs = exports.createFocusManager = exports.EventEmitter = exports.scrollIntoView = exports.createProxyProps = exports.isClickable = exports.wrapFunction = exports.safeInvoke = void 0;

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _react = _interopRequireDefault(require("react"));

var _scrollIntoViewIfNeeded = _interopRequireDefault(require("scroll-into-view-if-needed"));

// Copyright 1999-2020. Plesk International GmbH. All rights reserved.
const safeInvoke = (fn, ...args) => {
  if (typeof fn === 'function') {
    fn(...args);
  }
};

exports.safeInvoke = safeInvoke;

const wrapFunction = (fn, wrapper) => (...args) => {
  safeInvoke(fn, ...args);
  safeInvoke(wrapper, ...args);
};

exports.wrapFunction = wrapFunction;

const isClickable = e => {
  const {
    target,
    currentTarget
  } = e;

  if (false === (target instanceof HTMLElement && currentTarget.contains(target))) {
    return true;
  }

  if (target instanceof HTMLElement && target.hasAttribute('disabled')) {
    return false;
  }

  let element = target;

  while (element && element !== currentTarget) {
    if (element instanceof HTMLElement) {
      switch (element.nodeName) {
        case 'A':
        case 'INPUT':
        case 'BUTTON':
        case 'LABEL':
          return true;
      }

      if (element.getAttribute('role') === 'button') {
        return true;
      }

      element = element.parentNode;
    } else {
      return true;
    }
  }

  return false;
};

exports.isClickable = isClickable;

const createProxyProps = cb => {
  const ProxyProps = props => cb(props);

  return /*#__PURE__*/_react.default.createElement(ProxyProps, null);
};

exports.createProxyProps = createProxyProps;

const scrollIntoView = (target, options) => (0, _scrollIntoViewIfNeeded.default)(target, {
  block: 'center',
  behavior: 'smooth',
  ...options
});

exports.scrollIntoView = scrollIntoView;

class EventEmitter {
  constructor() {
    (0, _defineProperty2.default)(this, "listeners", {});
  }

  on(type, handler) {
    if (this.listeners[type] === undefined) {
      this.listeners[type] = [];
    }

    this.listeners[type].push(handler);
  }

  emit(type, ...args) {
    const handlers = this.listeners[type];

    if (handlers) {
      handlers.forEach(handler => {
        if (typeof handler === 'function') {
          handler(...args);
        }
      });
    }
  }

}

exports.EventEmitter = EventEmitter;

const createStrategy = () => {
  const getNext = (container, element) => {
    const elements = container.children;
    const index = Array.prototype.indexOf.call(elements, element);

    if (index !== -1) {
      return elements[index + 1];
    }

    return undefined;
  };

  const getPrev = (container, element) => {
    const elements = container.children;
    const index = Array.prototype.indexOf.call(elements, element);

    if (index !== -1) {
      return elements[index - 1];
    }

    return undefined;
  };

  const getFirst = container => {
    return container.firstElementChild;
  };

  const getLast = container => {
    return container.lastElementChild;
  };

  return {
    getNext,
    getPrev,
    getFirst,
    getLast
  };
};

const createFocusManager = (containerRef, // eslint-disable-next-line @typescript-eslint/no-unused-vars
isFitForFocus = _node => true, strategy = createStrategy()) => {
  const tryFocus = node => {
    if (isFitForFocus(node) && node instanceof HTMLElement) {
      node.focus();
      return true;
    }

    return false;
  };

  const focusNext = (element = document.activeElement, attempt = 0) => {
    if (!containerRef.current) {
      return false;
    }

    const next = strategy.getNext(containerRef.current, element);

    if (next) {
      if (tryFocus(next) || focusNext(next, attempt)) {
        return true;
      }
    }

    return focusFirst(attempt + 1);
  };

  const focusPrev = (element = document.activeElement, attempt = 0) => {
    if (!containerRef.current) {
      return false;
    }

    const prev = strategy.getPrev(containerRef.current, element);

    if (prev) {
      if (tryFocus(prev) || focusPrev(prev, attempt)) {
        return true;
      }
    }

    return focusLast(attempt + 1);
  };

  const focusFirst = (attempt = 0) => {
    if (attempt > 1) {
      return false;
    }

    if (!containerRef.current) {
      return false;
    }

    const next = strategy.getFirst(containerRef.current);

    if (next) {
      if (tryFocus(next) || focusNext(next, attempt)) {
        return true;
      }
    }

    return false;
  };

  const focusLast = (attempt = 0) => {
    if (attempt > 1) {
      return false;
    }

    if (!containerRef.current) {
      return false;
    }

    const prev = strategy.getLast(containerRef.current);

    if (prev) {
      if (tryFocus(prev) || focusPrev(prev, attempt)) {
        return true;
      }
    }

    return false;
  };

  return {
    focusNext,
    focusPrev,
    focusFirst,
    focusLast
  };
};

exports.createFocusManager = createFocusManager;

const mergeRefs = (...refs) => value => {
  refs.forEach(ref => {
    if (typeof ref === 'function') {
      ref(value);
    } else if (ref) {
      ref.current = value;
    }
  });
};

exports.mergeRefs = mergeRefs;