import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf";
import _assertThisInitialized from "@babel/runtime/helpers/esm/assertThisInitialized";
import _createClass from "@babel/runtime/helpers/esm/createClass";
import _inherits from "@babel/runtime/helpers/esm/inherits";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import React, { PureComponent, Children, isValidElement, cloneElement } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import MenuContext from './MenuContext';

function diff(a, b, propNames) {
  var result = false;
  propNames.forEach(function (name) {
    if (a[name] !== b[name]) {
      result = true;
    }
  });
  return result;
}

function getMenuItems(children) {
  var items = [];
  Children.forEach(children, function (item) {
    if (isValidElement(item)) {
      items.push(item);
    }
  });
  return items;
}

function getValue(value) {
  if (Array.isArray) {
    return value;
  }

  if (value != null) {
    return [value];
  }

  return [];
}
/**
 *  Menu
 */


var Menu =
/*#__PURE__*/
function (_PureComponent) {
  _inherits(Menu, _PureComponent);

  _createClass(Menu, null, [{
    key: "getDerivedStateFromProps",
    // TODO: 存在性能问题
    value: function getDerivedStateFromProps(props, state) {
      var propNames = ['autoFold', 'multiple', 'selectable', 'autoIndent', 'mode', 'size', 'indentBase'];
      var autoFold = props.autoFold,
          multiple = props.multiple,
          selectable = props.selectable,
          autoIndent = props.autoIndent,
          indent = props.indent,
          value = props.value,
          mode = props.mode,
          defaultValue = props.defaultValue,
          size = props.size,
          indentBase = props.indentBase;

      if (state.isControlled) {
        propNames.push('value');
      }

      if (diff(props, state.store, propNames) || defaultValue !== state.prevDefaultValue) {
        return {
          prevDefaultValue: defaultValue,
          store: {
            autoFold: autoFold,
            multiple: multiple,
            selectable: selectable,
            autoIndent: autoIndent,
            indent: indent,
            value: state.isControlled ? value : getValue(defaultValue),
            onSelect: state.store.onSelect,
            size: size,
            indentBase: indentBase,
            mode: mode
          }
        };
      }

      return null;
    }
  }]);

  function Menu(props, context) {
    var _this;

    _classCallCheck(this, Menu);

    _this = _possibleConstructorReturn(this, _getPrototypeOf(Menu).call(this, props, context));

    _defineProperty(_assertThisInitialized(_this), "updateStore", function (newValue) {
      _this.setState(function (state) {
        return {
          store: Object.assign({}, state.store, newValue)
        };
      });
    });

    _defineProperty(_assertThisInitialized(_this), "onSelect", function (e, itemValue) {
      var _this$props = _this.props,
          onSelect = _this$props.onSelect,
          onChange = _this$props.onChange,
          selectable = _this$props.selectable,
          multiple = _this$props.multiple,
          propsValue = _this$props.value;
      var store = _this.state.store;
      var value = selectable ? _this.isControlled ? propsValue : store.value : [];
      value = Array.isArray(value) ? value : [value];
      onSelect && onSelect(e, itemValue);

      if (selectable) {
        if (multiple) {
          var itemIndex = value.indexOf(itemValue);
          value = _toConsumableArray(value);

          if (itemIndex === -1) {
            value.push(itemValue);
          } else {
            value.splice(itemIndex, 1);
          }

          if (!_this.isControlled) {
            _this.updateStore({
              value: value
            });
          }
        } else if (!_this.isControlled) {
          _this.updateStore({
            value: [itemValue]
          });
        }
      }

      if (selectable && !value.includes(itemValue) || multiple) {
        onChange && onChange(e, multiple ? value : itemValue, itemValue);
      }
    });

    var defaultValue = props.defaultValue,
        _multiple = props.multiple,
        _value = props.value,
        _selectable = props.selectable,
        autoFold = props.autoFold,
        autoIndent = props.autoIndent,
        indent = props.indent,
        mode = props.mode,
        size = props.size,
        indentBase = props.indentBase;
    _this.isControlled = _value != null;
    var menuValue = _this.isControlled ? _value : getValue(defaultValue);
    _this.state = {
      prevDefaultValue: defaultValue,
      isControlled: _this.isControlled,
      store: {
        autoFold: autoFold,
        multiple: _multiple,
        selectable: _selectable,
        autoIndent: autoIndent,
        indent: indent,
        indentBase: indentBase,
        value: menuValue,
        onSelect: _this.onSelect,
        size: size,
        mode: mode
      }
    };
    return _this;
  }

  _createClass(Menu, [{
    key: "render",
    value: function render() {
      var _classNames;

      var _this$props2 = this.props,
          children = _this$props2.children,
          prefixCls = _this$props2.prefixCls,
          className = _this$props2.className,
          selectable = _this$props2.selectable,
          autoFold = _this$props2.autoFold,
          disableAutoIndent = _this$props2.disableAutoIndent,
          value = _this$props2.value,
          defaultValue = _this$props2.defaultValue,
          onSelect = _this$props2.onSelect,
          onChange = _this$props2.onChange,
          level = _this$props2.level,
          autoIndent = _this$props2.autoIndent,
          indent = _this$props2.indent,
          compact = _this$props2.compact,
          size = _this$props2.size,
          indentBase = _this$props2.indentBase,
          other = _objectWithoutProperties(_this$props2, ["children", "prefixCls", "className", "selectable", "autoFold", "disableAutoIndent", "value", "defaultValue", "onSelect", "onChange", "level", "autoIndent", "indent", "compact", "size", "indentBase"]);

      var store = this.state.store;
      var classes = classNames(prefixCls, (_classNames = {}, _defineProperty(_classNames, "".concat(prefixCls, "-compact"), compact), _defineProperty(_classNames, "".concat(prefixCls, "-size-").concat(size), size), _classNames), className);
      var menu = getMenuItems(children).map(function (item, key) {
        if (!React.isValidElement(item)) {
          return null;
        }

        var newProps = {
          level: level,
          size: size,
          key: item.props.value != null ? item.props.value : "menu-".concat(key)
        };

        if (compact) {
          newProps.compact = true;
        }

        if (item.type.isSubMenu && compact) {
          newProps.mode = 'popup';
          newProps.trigger = 'click';
        }

        return cloneElement(item, newProps);
      });
      return React.createElement(MenuContext.Provider, {
        value: store
      }, React.createElement("ul", _extends({
        className: classes
      }, other), menu));
    }
  }]);

  return Menu;
}(PureComponent);

_defineProperty(Menu, "propTypes", {
  /**
   * 类前缀
   * */
  prefixCls: PropTypes.string,

  /** 是否自动折叠 */
  autoFold: PropTypes.bool,

  /** 是否可选中 */
  selectable: PropTypes.bool,

  /** 是否可以多选 */
  multiple: PropTypes.bool,

  /** 默认值 */
  defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool, PropTypes.array]),

  /**
   * 当前值，适用于受控模式下使用
   */
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool, PropTypes.array]),

  /** 是否自动缩进 */
  autoIndent: PropTypes.bool,

  /** 缩进长度（单位px） */
  indent: PropTypes.number,

  /** 值改变时回调 function(e, value) */
  onChange: PropTypes.func,

  /** 选择菜单中一项时回调 function(e, value) */
  onSelect: PropTypes.func,

  /** 当前菜单层数（计算缩进使用） */
  level: PropTypes.number,

  /** 同原生role属性 */
  role: PropTypes.string,

  /** 子菜单模式（内联，弹出，多级） */
  mode: PropTypes.oneOf(['inline', 'popup', 'parallel']),

  /** 尺寸 */
  size: PropTypes.oneOf(['small', 'medium', 'large']),

  /** 是否为紧凑模式 */
  compact: PropTypes.bool
});

_defineProperty(Menu, "defaultProps", {
  defaultValue: [],
  prefixCls: 'ne-menu',
  selectable: false,
  autoFold: false,
  autoIndent: true,
  multiple: false,
  level: 1,
  indent: 14,
  role: 'menu',
  mode: 'inline',
  size: 'medium',
  compact: false,
  indentBase: 8
});

_defineProperty(Menu, "displayName", 'NeatUI.Menu');

export default Menu;