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 _createClass from "@babel/runtime/helpers/esm/createClass";
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 _inherits from "@babel/runtime/helpers/esm/inherits";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";

/**
 * cascader.jsx
 *
 * @Author: zhangce
 * @Date: 17/8/29 下午2:28
 */
import React, { cloneElement } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Input, Menu, MenuItem, ParallelMenu, DropdownMenu } from '../index';
import ExpandMore from '../icons/internals/ExpandMore';
import { arrayTreeFilter, treeToPath } from '../util/arrayTreeFilter';
import { isEqualArrays } from '../util/isEqual';
/**
 * Cascader
 * */

var Cascader =
/*#__PURE__*/
function (_React$PureComponent) {
  _inherits(Cascader, _React$PureComponent);

  function Cascader(_props) {
    var _this;

    _classCallCheck(this, Cascader);

    _this = _possibleConstructorReturn(this, _getPrototypeOf(Cascader).call(this, _props));

    _defineProperty(_assertThisInitialized(_this), "getDefaultOptions", function (props) {
      var defaultValue = props.defaultValue,
          childrenKeyName = props.childrenKeyName;
      return defaultValue.length ? arrayTreeFilter(_this.options, function (o, level) {
        return o.value === defaultValue[level];
      }, null, {
        childrenKeyName: childrenKeyName
      }) : [];
    });

    _defineProperty(_assertThisInitialized(_this), "updateOptions", function (props) {
      var searchable = props.searchable;

      if (props.options) {
        _this.options = props.options;
      } else {
        _this.options = _this.getTreeMapOptions(props.children);
      }

      if (searchable) {
        _this.pathOptions = treeToPath(_this.options);
      }
    });

    _defineProperty(_assertThisInitialized(_this), "getTreeMapOptions", function (children) {
      return React.Children.map(children, function (ele) {
        var props = ele.props;
        var option;

        if (ele.type.isSubMenu) {
          option = {
            value: props.value,
            label: props.title,
            disabled: props.disabled || false,
            children: _this.getTreeMapOptions(props.children)
          };
        } else if (ele.type.isMenuItem) {
          option = {
            value: props.value,
            disabled: props.disabled || false,
            label: props.children,
            isLastNode: props.isLastNode !== false
          };
        }

        return option;
      });
    });

    _defineProperty(_assertThisInitialized(_this), "onChange", function (value, isLast) {
      var _this$props = _this.props,
          searchable = _this$props.searchable,
          loadOptionData = _this$props.loadOptionData,
          childrenKeyName = _this$props.childrenKeyName;

      var selectOptionMap = _this.getDefaultOptions({
        defaultValue: _toConsumableArray(value)
      });

      _this.handleValueChange(selectOptionMap, !isLast);

      if (!searchable && loadOptionData) {
        var lastOption = selectOptionMap[selectOptionMap.length - 1];

        if (lastOption.isLastNode === false && lastOption[childrenKeyName] === undefined) {
          loadOptionData(selectOptionMap.map(function (o) {
            return o.value;
          }), selectOptionMap);

          _this.setState({
            defaultIsOpen: true
          });
        }
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handleSelect", function (e, value, isLast, level, selectedValue) {
      var onSelect = _this.props.onSelect;
      if (_this.searchInput) _this.searchInput.focus();

      _this.setState({
        selectedValue: selectedValue
      });

      if (isLast) {
        _this.setState({
          defaultIsOpen: false
        });
      }

      onSelect && onSelect(e, value, isLast);
    });

    _defineProperty(_assertThisInitialized(_this), "handleMenuVisibleChange", function (isOpen) {
      var onPopVisibleChange = _this.props.onPopVisibleChange;

      if (isOpen) {
        _this.setState({
          defaultIsOpen: true,
          searchDefaultIsOpen: false
        });
      } else {
        _this.setState({
          defaultIsOpen: false,
          inputValue: ''
        });
      }

      onPopVisibleChange && onPopVisibleChange(isOpen);
    });

    _defineProperty(_assertThisInitialized(_this), "clearValue", function (e) {
      var _this$props2 = _this.props,
          onChange = _this$props2.onChange,
          searchable = _this$props2.searchable;
      var inputValue = _this.state.inputValue; // 清理搜索框值

      if (searchable && inputValue !== '') {
        _this.setState({
          inputValue: '',
          searchDefaultIsOpen: false
        });

        return;
      }

      e && e.stopPropagation && e.stopPropagation(); // 清理组件选中值

      _this.setState({
        value: [],
        selectOptionMap: []
      }); // 触发onChange


      onChange([], []);
    });

    _defineProperty(_assertThisInitialized(_this), "handleMenuClose", function () {
      _this.setState({
        inputValue: '',
        defaultIsOpen: false,
        searchDefaultIsOpen: false
      });
    });

    _defineProperty(_assertThisInitialized(_this), "handleSearch", function (e) {
      var inputValue = e.target.value;

      _this.setState({
        inputValue: inputValue,
        searchDefaultIsOpen: inputValue.length > 0
      }, function () {
        var result = [];

        _this.pathOptions.forEach(function (item) {
          var _iteratorNormalCompletion = true;
          var _didIteratorError = false;
          var _iteratorError = undefined;

          try {
            for (var _iterator = item[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
              var o = _step.value;
              var label = o.label;

              if (label.match(inputValue) !== null) {
                result.push(item);
                break;
              }
            }
          } catch (err) {
            _didIteratorError = true;
            _iteratorError = err;
          } finally {
            try {
              if (!_iteratorNormalCompletion && _iterator.return != null) {
                _iterator.return();
              }
            } finally {
              if (_didIteratorError) {
                throw _iteratorError;
              }
            }
          }
        });

        _this.setState({
          searchResult: result
        });
      });
    });

    _defineProperty(_assertThisInitialized(_this), "handleSearchResultSelect", function (e, value) {
      var searchResult = _this.state.searchResult;
      var result = searchResult[value];

      _this.handleValueChange(result, false);
    });

    _defineProperty(_assertThisInitialized(_this), "handleValueChange", function (optionMap, isOpen) {
      var onChange = _this.props.onChange;
      var newValue = optionMap.map(function (o) {
        return o.value;
      });

      _this.setState(function (prevState, props) {
        if (!isEqualArrays(prevState.value, newValue)) {
          onChange && onChange(newValue, optionMap);
          return {
            value: newValue,
            selectOptionMap: _toConsumableArray(optionMap)
          };
        }
      });

      _this.setState({
        defaultIsOpen: isOpen
      });
    });

    _defineProperty(_assertThisInitialized(_this), "initSearchResult", function () {
      var _this$props3 = _this.props,
          noResultHolder = _this$props3.noResultHolder,
          prefixCls = _this$props3.prefixCls;
      var searchResult = _this.state.searchResult;
      var menuItems = searchResult.length ? searchResult.map(function (item, index) {
        var label = [];
        var optionValue = [];
        var disabled = false;
        item.forEach(function (o) {
          label.push(o.label);
          optionValue.push(o.value);

          if (o.disabled) {
            disabled = true;
          }
        });
        return React.createElement(MenuItem, {
          value: index,
          disabled: disabled,
          key: index
        }, label.join('/'));
      }) : React.createElement(MenuItem, {
        key: "notFond",
        disabled: true
      }, noResultHolder);
      return React.createElement(Menu, {
        selectable: true,
        className: "".concat(prefixCls, "-search-menu")
      }, menuItems);
    });

    _defineProperty(_assertThisInitialized(_this), "getMaskRef", function (mask) {
      _this.mask = mask;
    });

    _defineProperty(_assertThisInitialized(_this), "getInputRef", function (input) {
      _this.searchInput = input;
    });

    _defineProperty(_assertThisInitialized(_this), "handleClick", function () {
      var onClick = _this.props.onClick;
      var defaultIsOpen = _this.state.defaultIsOpen;
      onClick && onClick();

      if (_this.options.length) {
        _this.handleMenuVisibleChange(!defaultIsOpen);
      }
    });

    _this.options = [];

    _this.updateOptions(_props);

    _this.selectedValue = _props.defaultValue;
    _this.state = {
      selectOptionMap: _this.getDefaultOptions(_props),
      value: _props.defaultValue,
      selectedValue: _props.defaultValue,
      inputValue: '',
      searchResult: [],
      defaultIsOpen: false,
      searchDefaultIsOpen: false
    };
    return _this;
  }

  _createClass(Cascader, [{
    key: "componentWillReceiveProps",
    value: function componentWillReceiveProps(newProps) {
      if (newProps.children !== this.props.children) {
        this.updateOptions(newProps);
      }

      if (newProps.defaultValue !== this.props.defaultValue) {
        this.setState({
          value: newProps.defaultValue,
          selectedValue: newProps.defaultValue,
          selectOptionMap: this.getDefaultOptions(newProps)
        });
      }
    }
  }, {
    key: "componentDidUpdate",
    value: function componentDidUpdate(prevProps, prevState) {
      var _this$state = this.state,
          defaultIsOpen = _this$state.defaultIsOpen,
          selectedValue = _this$state.selectedValue,
          value = _this$state.value;
      var defaultIsOpenChanged = prevState.defaultIsOpen !== defaultIsOpen;

      if (defaultIsOpen) {
        this.searchInput && this.searchInput.focus();

        if (defaultIsOpenChanged && selectedValue !== value && !isEqualArrays(selectedValue, value)) {
          this.setState({
            selectedValue: value
          });
        }
      }
    }
  }, {
    key: "renderLabel",
    value: function renderLabel() {
      var labelRender = this.props.labelRender;
      var selectOptionMap = this.state.selectOptionMap;
      var labelMap = selectOptionMap.map(function (o) {
        return o.label;
      });
      return labelRender ? labelRender(labelMap) : labelMap.join('/');
    }
  }, {
    key: "renderInput",
    value: function renderInput() {
      var _this$props4 = this.props,
          prefixCls = _this$props4.prefixCls,
          className = _this$props4.className,
          placeholder = _this$props4.placeholder,
          searchable = _this$props4.searchable,
          anchorEl = _this$props4.anchorEl,
          inputProps = _this$props4.inputProps,
          style = _this$props4.style,
          size = _this$props4.size,
          fullWidth = _this$props4.fullWidth,
          status = _this$props4.status,
          clearIcon = _this$props4.clearIcon,
          errorIcon = _this$props4.errorIcon,
          loadingIcon = _this$props4.loadingIcon,
          successIcon = _this$props4.successIcon,
          showStatusIcon = _this$props4.showStatusIcon,
          disabled = _this$props4.disabled,
          clearable = _this$props4.clearable,
          id = _this$props4.id;
      var _this$state2 = this.state,
          defaultIsOpen = _this$state2.defaultIsOpen,
          inputValue = _this$state2.inputValue;
      var classString = classNames(prefixCls, className);
      return anchorEl ? cloneElement(anchorEl, {
        onClick: this.handleClick
      }) : React.createElement(Input, {
        id: id,
        type: "text",
        className: classString,
        placeholder: placeholder,
        inputRef: this.getInputRef,
        value: inputValue || this.renderLabel(),
        disabled: disabled,
        mask: !searchable || searchable && !defaultIsOpen ? this.renderLabel() : undefined,
        onClick: this.handleClick,
        onChange: this.handleSearch,
        fullWidth: fullWidth,
        status: status,
        clearable: clearable,
        onClear: this.clearValue,
        clearIcon: clearIcon,
        errorIcon: errorIcon,
        loadingIcon: loadingIcon,
        successIcon: successIcon,
        showStatusIcon: showStatusIcon,
        readOnly: !searchable,
        suffix: React.createElement(ExpandMore, {
          className: classNames("".concat(prefixCls, "-arrow"))
        }),
        inputProps: inputProps,
        style: style,
        size: size
      });
    }
  }, {
    key: "render",
    value: function render() {
      var _this$props5 = this.props,
          prefixCls = _this$props5.prefixCls,
          pickerClass = _this$props5.pickerClass,
          children = _this$props5.children,
          changeOnSelect = _this$props5.changeOnSelect,
          options = _this$props5.options,
          position = _this$props5.position,
          trigger = _this$props5.trigger,
          defaultValue = _this$props5.defaultValue,
          searchable = _this$props5.searchable,
          noResultHolder = _this$props5.noResultHolder,
          loadOptionData = _this$props5.loadOptionData,
          labelRender = _this$props5.labelRender,
          onChange = _this$props5.onChange,
          anchorEl = _this$props5.anchorEl,
          inputProps = _this$props5.inputProps,
          size = _this$props5.size,
          status = _this$props5.status,
          clearIcon = _this$props5.clearIcon,
          errorIcon = _this$props5.errorIcon,
          loadingIcon = _this$props5.loadingIcon,
          successIcon = _this$props5.successIcon,
          showStatusIcon = _this$props5.showStatusIcon,
          disabled = _this$props5.disabled,
          id = _this$props5.id,
          scrollContainer = _this$props5.scrollContainer,
          other = _objectWithoutProperties(_this$props5, ["prefixCls", "pickerClass", "children", "changeOnSelect", "options", "position", "trigger", "defaultValue", "searchable", "noResultHolder", "loadOptionData", "labelRender", "onChange", "anchorEl", "inputProps", "size", "status", "clearIcon", "errorIcon", "loadingIcon", "successIcon", "showStatusIcon", "disabled", "id", "scrollContainer"]);

      var _this$state3 = this.state,
          defaultIsOpen = _this$state3.defaultIsOpen,
          searchDefaultIsOpen = _this$state3.searchDefaultIsOpen,
          selectedValue = _this$state3.selectedValue;
      return React.createElement(DropdownMenu, {
        noClose: true,
        disabled: disabled,
        defaultIsOpen: defaultIsOpen,
        anchorEl: this.renderInput(),
        onSelect: searchDefaultIsOpen ? this.handleSearchResultSelect : this.handleSelect,
        onOpenChange: this.handleMenuVisibleChange,
        className: pickerClass,
        trigger: trigger,
        position: position,
        scrollContainer: scrollContainer
      }, searchDefaultIsOpen ? this.initSearchResult() : React.createElement(ParallelMenu, _extends({
        disabled: disabled,
        className: "".concat(prefixCls, "-menu"),
        defaultValue: selectedValue,
        options: options,
        onChange: this.onChange,
        changeOnSelect: changeOnSelect
      }, other), children));
    }
  }]);

  return Cascader;
}(React.PureComponent);

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

  /**
   * 类名
   * */
  className: PropTypes.string,

  /**
   * 树结构值（传options就不要传子组件）
   * */
  options: PropTypes.array,

  /**
   * input placeholder
   * */
  placeholder: PropTypes.string,

  /**
   * 搜索无文本提示文字
   * */
  noResultHolder: PropTypes.string,

  /**
   * 默认选中值
   * */
  defaultValue: PropTypes.array,

  /**
   * 是否选中改变
   * */
  changeOnSelect: PropTypes.bool,

  /**
   * 是否可搜索（异步不可以搜索）
   * */
  searchable: PropTypes.bool,

  /**
   * 输入框点击回调
   * */
  onClick: PropTypes.func,

  /**
   * 值改变回调
   * */
  onChange: PropTypes.func,

  /**
   * 选中menuItem回调
   * */
  onSelect: PropTypes.func,

  /**
   * 异步获取数据函数
   * */
  loadOptionData: PropTypes.func,

  /**
   * 选项菜单显示关闭回调
   * */
  onPopVisibleChange: PropTypes.func,

  /**
   * 选中内容后展示回调
   * */
  labelRender: PropTypes.func,

  /**
   * 触发显示选中菜单元素
   * */
  anchorEl: PropTypes.element,

  /**
   * 自定义样式
   * */
  style: PropTypes.object,

  /**
   * 选择框大小，默认medium，base同medium
   * */
  size: PropTypes.oneOf(['large', 'medium', 'small', 'base']),
  // base === medium

  /**
   * 当为默认input输入框触发时，`Input`组件的props
   * */
  inputProps: PropTypes.object,

  /**
   * 下拉选项框类名
   * */
  pickerClass: PropTypes.string,

  /**
   * 触发方式
   * */
  trigger: PropTypes.oneOf(['click', 'focus', 'hover']),

  /**
   * options子元素key值
   * */
  childrenKeyName: PropTypes.string,

  /**
   *  scrollContainer Tooltip兼容自定义可滚动容器
   */
  scrollContainer: PropTypes.node
});

_defineProperty(Cascader, "defaultProps", {
  prefixCls: 'ne-cascader-picker',
  placeholder: '',
  size: 'medium',
  changeOnSelect: false,
  searchable: false,
  defaultValue: [],
  noResultHolder: 'Not Found',
  trigger: 'focus',
  position: 'bottomLeft',
  childrenKeyName: 'children'
});

export default Cascader;