import "core-js/modules/web.dom.iterable";
import "core-js/modules/es6.array.iterator";
import "core-js/modules/es6.object.keys";
import "core-js/modules/es6.object.assign";
import "core-js/modules/es6.regexp.match";
import "core-js/modules/es7.array.includes";
import "core-js/modules/es6.string.includes";

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }

import React from 'react';
import PropTypes from 'prop-types';
import { isEqual } from 'lodash';
/**
 * Menu is container component which contains MenuItems
 * @component Menu
 * @variations collab-ui-react
 */

var Menu =
/*#__PURE__*/
function (_React$Component) {
  _inheritsLoose(Menu, _React$Component);

  function Menu() {
    var _this;

    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;
    _this.state = {
      menuIndex: []
    };

    _this.getChildContext = function () {
      return {
        handleClick: _this.handleClick,
        handleKeyDown: _this.handleKeyDown
      };
    };

    _this.handleClick = function (e, menuItemIndex, menuItem) {
      var onSelect = _this.context.onSelect;
      var children = menuItem.props.children;

      var selectedChildIndex = children && _this.getNewIndex(-1, 1, React.Children.toArray(children));

      _this.setState({
        menuIndex: children ? menuItemIndex.concat(selectedChildIndex) : [menuItemIndex[0]]
      }, function () {
        return onSelect && onSelect(e, menuItemIndex, menuItem);
      });
    };

    _this.getNewIndex = function (currentIndex, change, siblings) {
      var getPossibleIndex = function getPossibleIndex() {
        var length = siblings.length - 1;

        if (currentIndex + change < 0) {
          return length;
        } else if (currentIndex + change > length) {
          return 0;
        }

        return currentIndex + change;
      };

      var possibleIndex = getPossibleIndex();
      var potentialTarget = React.Children.toArray(siblings)[possibleIndex];
      return potentialTarget.props.disabled || potentialTarget.props.isHeader ? _this.getNewIndex(possibleIndex, change, siblings) : possibleIndex;
    };

    _this.setFocusInCurrentMenu = function (newIndex) {
      var menuIndex = _this.state.menuIndex;
      var clonedIndex = !menuIndex.length ? newIndex.concat() : menuIndex.slice(0, menuIndex.length - 1).concat([newIndex]);

      _this.setState({
        menuIndex: clonedIndex
      });
    };

    _this.handleKeyDown = function (e, selectedIndex, menuItem) {
      var menuIndex = _this.state.menuIndex;
      var children = _this.props.children;
      var onSelect = _this.context.onSelect;
      var subMenu = menuItem.props.children;

      var subMenuIndex = subMenu && _this.getNewIndex(-1, 1, React.Children.toArray(subMenu));

      var originIndex = selectedIndex[selectedIndex.length - 1];

      var getSiblings = function getSiblings(idx, menuItems) {
        if (menuItems === void 0) {
          menuItems = children;
        }

        if (idx.length === 1) {
          return menuItems;
        }

        return getSiblings(idx.slice(1), React.Children.toArray(menuItems[idx[0]].props.children));
      };

      var getIncludesFirstCharacter = function getIncludesFirstCharacter(str, char) {
        return str.charAt(0).toLowerCase().includes(char);
      };

      var setFocusByFirstCharacter = function setFocusByFirstCharacter(char, currentIdx) {
        var siblings = getSiblings(currentIdx);
        var length = siblings.length - 1;
        var indexInSubmenu = currentIdx[currentIdx.length - 1];
        var newIndex = React.Children.toArray(siblings).reduce(function (agg, child, idx, arr) {
          var index = indexInSubmenu + idx + 1 > length ? Math.abs(indexInSubmenu + idx - length) : indexInSubmenu + idx + 1;
          var label = arr[index].props.label;
          return !agg.length && !arr[index].props.disabled && !arr[index].props.isReadOnly && getIncludesFirstCharacter(label, char) ? agg.concat(index) : agg;
        }, []);
        !isNaN(newIndex[0]) && _this.setFocusInCurrentMenu(newIndex[0]);
      };

      var isPrintableCharacter = function isPrintableCharacter(str) {
        return str.length === 1 && str.match(/\S/);
      };

      var flag = false;
      var char = e.key;

      switch (e.which) {
        case 38:
          _this.setFocusInCurrentMenu(_this.getNewIndex(originIndex, -1, getSiblings(selectedIndex)));

          flag = true;
          break;

        case 40:
          _this.setFocusInCurrentMenu(_this.getNewIndex(originIndex, 1, getSiblings(selectedIndex)));

          flag = true;
          break;

        case 39:
          //right
          subMenu && _this.setState({
            menuIndex: menuIndex.concat(subMenuIndex)
          }, function () {
            return onSelect && onSelect(e, menuIndex, menuItem);
          });
          flag = true;
          break;

        case 37:
          //left
          menuIndex.length - 1 && _this.setState({
            menuIndex: menuIndex.slice(0, menuIndex.length - 1)
          });
          flag = true;
          break;

        default:
          if (isPrintableCharacter(char)) {
            setFocusByFirstCharacter(char, selectedIndex);
            flag = true;
          }

          break;
      }

      if (flag) {
        e.stopPropagation();
        e.preventDefault();
      }
    };

    return _this;
  }

  var _proto = Menu.prototype;

  _proto.componentWillMount = function componentWillMount() {
    var children = this.props.children;
    var initialIndex = this.getNewIndex(-1, 1, React.Children.toArray(children));
    this.setState({
      menuIndex: [initialIndex]
    });
  };

  _proto.render = function render() {
    var _this$props = this.props,
        ariaLabel = _this$props.ariaLabel,
        children = _this$props.children,
        className = _this$props.className,
        props = _objectWithoutPropertiesLoose(_this$props, ["ariaLabel", "children", "className"]);

    var menuIndex = this.state.menuIndex;

    var setMenuItems = function setMenuItems(menuList, currentItemIndex) {
      if (currentItemIndex === void 0) {
        currentItemIndex = [];
      }

      return React.Children.toArray(menuList).map(function (child, idx) {
        if (!child.type || !['MenuItem', 'SubMenu'].includes(child.type.displayName)) {
          throw new Error('[@collab-ui/react] Menu: children of Menu should be of type MenuItem or SubMenu');
        }

        var menuItemIndex = currentItemIndex.concat(idx);
        var menuItems = child.props.children;
        var focus = isEqual(menuIndex, menuItemIndex);
        var isOpen = isEqual(menuIndex.slice(0, menuItemIndex.length), menuItemIndex) && menuIndex.length !== menuItemIndex.length;
        return React.cloneElement(child, Object.assign({
          index: menuItemIndex,
          focus: focus,
          isOpen: isOpen
        }, child.type.displayName === 'SubMenu' && {
          children: menuItems && setMenuItems(React.Children.toArray(menuItems), menuItemIndex)
        }));
      });
    };

    return React.createElement("div", _extends({
      className: 'cui-menu' + ' cui-menu-item-container' + ("" + (className && " " + className || '')),
      "aria-label": ariaLabel,
      role: "menubar"
    }, props), setMenuItems(children));
  };

  return Menu;
}(React.Component);

Menu.displayName = 'Menu';
Menu.childContextTypes = {
  handleClick: PropTypes.func,
  handleKeyDown: PropTypes.func
};
export { Menu as default };
Menu.contextTypes = {
  onSelect: PropTypes.func
};
Menu.propTypes = {
  ariaLabel: PropTypes.string,
  children: PropTypes.node,
  className: PropTypes.string
};
Menu.defaultProps = {
  ariaLabel: '',
  children: null,
  className: ''
};