"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");

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

exports.__esModule = true;
exports.default = void 0;

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

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

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

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

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

var _pick2 = _interopRequireDefault(require("lodash/pick"));

var _kebabCase2 = _interopRequireDefault(require("lodash/kebabCase"));

var _isUndefined2 = _interopRequireDefault(require("lodash/isUndefined"));

var _get2 = _interopRequireDefault(require("lodash/get"));

var React = _interopRequireWildcard(require("react"));

var _classnames = _interopRequireDefault(require("classnames"));

var _rsuiteIntl = require("rsuite-intl");

var _utils = require("rsuite-utils/lib/utils");

var _reactLifecyclesCompat = require("react-lifecycles-compat");

var _DropdownMenu = _interopRequireDefault(require("./DropdownMenu"));

var _utils2 = require("../utils");

var _stringToObject2 = _interopRequireDefault(require("../utils/stringToObject"));

var _treeUtils = require("../utils/treeUtils");

var _picker = require("../_picker");

function getDerivedStateForCascade(nextProps, prevState, selectNodeValue, newChildren) {
  var data = nextProps.data,
      labelKey = nextProps.labelKey,
      valueKey = nextProps.valueKey,
      childrenKey = nextProps.childrenKey,
      value = nextProps.value;
  var activeItemValue = selectNodeValue || (typeof value === 'undefined' ? prevState.value : value);
  var nextItems = [];
  var nextPathItems = [];

  var findNode = function findNode(items) {
    var _loop = function _loop(i) {
      items[i] = (0, _stringToObject2.default)(items[i], labelKey, valueKey);
      var children = items[i][childrenKey];

      if ((0, _utils.shallowEqual)(items[i][valueKey], activeItemValue)) {
        return {
          v: {
            items: items,
            active: items[i]
          }
        };
      } else if (children) {
        var v = findNode(children);

        if (v) {
          nextItems.push(children.map(function (item) {
            return (0, _extends3.default)({}, (0, _stringToObject2.default)(item, labelKey, valueKey), {
              parent: items[i]
            });
          }));
          nextPathItems.push(v.active);
          return {
            v: {
              items: items,
              active: items[i]
            }
          };
        }
      }
    };

    for (var i = 0; i < items.length; i += 1) {
      var _ret = _loop(i);

      if (typeof _ret === "object") return _ret.v;
    }

    return null;
  };

  var activeItem = findNode(data);
  nextItems.push(data);

  if (activeItem) {
    nextPathItems.push(activeItem.active);
  }
  /**
   * 如果是异步更新 data 后，获取到的一个 selectNodeValue，则不更新 activePaths
   * 但是需要更新 items， 因为这里的目的就是把异步更新后的的数据展示出来
   */


  var cascadePathItems = nextPathItems.reverse();

  if (selectNodeValue) {
    return {
      items: [].concat(nextItems.reverse(), [newChildren]),
      tempActivePaths: cascadePathItems
    };
  }

  return {
    items: nextItems.reverse(),
    activePaths: cascadePathItems
  };
}

var Dropdown =
/*#__PURE__*/
function (_React$Component) {
  (0, _inheritsLoose2.default)(Dropdown, _React$Component);

  function Dropdown(props) {
    var _this;

    _this = _React$Component.call(this, props) || this;
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleSelect", function (node, cascadeItems, activePaths, isLeafNode, event) {
      var _this$props = _this.props,
          onChange = _this$props.onChange,
          onSelect = _this$props.onSelect,
          valueKey = _this$props.valueKey;

      var prevValue = _this.getValue();

      var value = node[valueKey];
      onSelect && onSelect(node, activePaths, (0, _picker.createConcatChildrenFunction)(node), event);
      /**
       * 只有在叶子节点的时候才当做是可以选择的值
       * 一个节点的 children 为 null 或者 undefined 的是就是叶子节点
       */

      if (isLeafNode) {
        _this.closeDropdown();

        var nextState = (0, _extends3.default)({
          selectNode: node
        }, getDerivedStateForCascade(_this.props, {
          value: value
        }));

        if (typeof _this.props.value === 'undefined') {
          nextState.value = value;
        }

        _this.setState(nextState);

        if (!(0, _utils.shallowEqual)(value, prevValue)) {
          onChange && onChange(value, event);
        }

        return;
      }

      _this.setState({
        selectNode: node,
        items: cascadeItems,
        tempActivePaths: activePaths
      });
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleSearchRowSelect", function (item, event) {
      var _this$props2 = _this.props,
          valueKey = _this$props2.valueKey,
          onChange = _this$props2.onChange;
      var value = item[valueKey];

      var _getDerivedStateForCa = getDerivedStateForCascade(_this.props, {
        value: value
      }),
          activePaths = _getDerivedStateForCa.activePaths,
          items = _getDerivedStateForCa.items;

      _this.closeDropdown();

      _this.setState({
        selectNode: item,
        searchKeyword: '',
        activePaths: activePaths,
        items: items,
        value: value
      });

      onChange && onChange(value, event);
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "trigger", null);
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "bindTriggerRef", function (ref) {
      _this.trigger = ref;
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "menuContainer", null);
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "bindMenuContainerRef", function (ref) {
      _this.menuContainer = ref;
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "container", null);
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "bindContainerRef", function (ref) {
      _this.container = ref;
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "closeDropdown", function () {
      if (_this.trigger) {
        _this.trigger.hide();
      }
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleClean", function (event) {
      var _this$props3 = _this.props,
          disabled = _this$props3.disabled,
          onChange = _this$props3.onChange,
          data = _this$props3.data;

      if (disabled) {
        return;
      }

      var nextState = {
        items: [data],
        value: null,
        selectNode: null,
        activePaths: [],
        tempActivePaths: []
      };

      _this.setState(nextState, function () {
        onChange && onChange(null, event);
      });
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleSearch", function (searchKeyword, event) {
      var onSearch = _this.props.onSearch; //     this.setState({
      //       searchKeyword
      //     });

      onSearch && onSearch(searchKeyword, event);
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleEntered", function () {
      var onOpen = _this.props.onOpen;
      onOpen && onOpen();

      _this.setState({
        active: true
      });
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleExit", function () {
      var onClose = _this.props.onClose;
      onClose && onClose();

      _this.setState({
        searchKeyword: '',
        active: false
      });
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "addPrefix", function (name) {
      return (0, _utils2.prefix)(_this.props.classPrefix)(name);
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "renderSearchRow", function (item, key) {
      var _extends2, _classNames;

      var _this$props4 = _this.props,
          labelKey = _this$props4.labelKey,
          valueKey = _this$props4.valueKey,
          _this$props4$disabled = _this$props4.disabledItemValues,
          disabledItemValues = _this$props4$disabled === void 0 ? [] : _this$props4$disabled;
      var searchKeyword = _this.state.searchKeyword;
      var nodes = (0, _treeUtils.getNodeParents)(item);
      var regx = new RegExp(searchKeyword, 'ig');
      var labelElements = [];
      var a = item[labelKey].split(regx);
      var b = item[labelKey].match(regx);

      for (var i = 0; i < a.length; i++) {
        labelElements.push(a[i]);

        if (b[i]) {
          labelElements.push(React.createElement("strong", {
            key: i
          }, b[i]));
        }
      }

      nodes.push((0, _extends3.default)({}, item, (_extends2 = {}, _extends2[labelKey] = labelElements, _extends2)));
      var disabled = disabledItemValues.some(function (value) {
        return nodes.some(function (node) {
          return node[valueKey] === value;
        });
      });
      var itemClasses = (0, _classnames.default)(_this.addPrefix('cascader-row'), (_classNames = {}, _classNames[_this.addPrefix('cascader-row-disabled')] = disabled, _classNames));
      return React.createElement("div", {
        key: key,
        className: itemClasses,
        onClick: function onClick(event) {
          if (!disabled) {
            _this.handleSearchRowSelect(item, event);
          }
        }
      }, nodes.map(function (node, index) {
        return React.createElement("span", {
          key: "col-" + index,
          className: _this.addPrefix('cascader-col')
        }, node[labelKey]);
      }));
    });
    var initState = {
      searchKeyword: '',
      selectNode: null,
      data: props.data,
      value: props.defaultValue,

      /**
       * 选中值的路径
       */
      activePaths: [],

      /**
       * 用于展示面板的数据列表，是一个二维的数组
       * 是通过 data 树结构转换成的二维的数组，其中只包含页面上展示的数据
       */
      items: []
    };
    _this.state = (0, _extends3.default)({}, initState, getDerivedStateForCascade(props, initState), {
      flattenData: (0, _treeUtils.flattenTree)(props.data)
    });
    return _this;
  }

  Dropdown.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
    var value = nextProps.value,
        data = nextProps.data,
        labelKey = nextProps.labelKey,
        valueKey = nextProps.valueKey;

    if (data !== prevState.data) {
      /**
       * 如果更新了 data,
       * 首先获取到被点击节点的值 `selectNodeValue`， 然后再拿到新增后的 `newChildren`,
       */
      var selectNodeValue = (0, _get2.default)(prevState, ['selectNode', valueKey]);
      var newChildren = (0, _get2.default)((0, _utils.findNodeOfTree)(data, function (item) {
        return (0, _utils.shallowEqual)(item[valueKey], selectNodeValue);
      }), 'children') || [];
      var nextState = getDerivedStateForCascade(nextProps, prevState, selectNodeValue, newChildren.map(function (item) {
        return (0, _stringToObject2.default)(item, labelKey, valueKey);
      }));
      return (0, _extends3.default)({}, nextState, {
        data: data,
        flattenData: (0, _treeUtils.flattenTree)(data)
      });
    } else if (typeof value !== 'undefined' && !(0, _utils.shallowEqual)(value, prevState.value)) {
      var _nextState = getDerivedStateForCascade(nextProps, prevState);

      return (0, _extends3.default)({}, _nextState, {
        value: value
      });
    }

    return null;
  };

  var _proto = Dropdown.prototype;

  _proto.getValue = function getValue(nextProps) {
    var _ref = nextProps || this.props,
        value = _ref.value;

    return (0, _isUndefined2.default)(value) ? this.state.value : value;
  };

  /**
   * 在 data 对象中的数据类型是字符串比如: ['foo']
   * 通过这个行数可以把值转换成 [{name:'foo':value:'foo'}]
   */
  _proto.stringToObject = function stringToObject(value) {
    var _this$props5 = this.props,
        labelKey = _this$props5.labelKey,
        valueKey = _this$props5.valueKey;
    return (0, _stringToObject2.default)(value, labelKey, valueKey);
  };

  _proto.getSearchResult = function getSearchResult() {
    var labelKey = this.props.labelKey;
    var _this$state = this.state,
        searchKeyword = _this$state.searchKeyword,
        flattenData = _this$state.flattenData;
    var items = [];
    var result = flattenData.filter(function (item) {
      if (item[labelKey].match(new RegExp(searchKeyword, 'i'))) {
        return true;
      }

      return false;
    });

    for (var i = 0; i < result.length; i++) {
      items.push(result[i]);

      if (i === 99) {
        return items;
      }
    }

    return items;
  };

  _proto.renderSearchResultPanel = function renderSearchResultPanel() {
    var locale = this.props.locale;
    var searchKeyword = this.state.searchKeyword;

    if (searchKeyword === '') {
      return null;
    }

    var items = this.getSearchResult();
    return React.createElement("div", {
      className: this.addPrefix('cascader-search-panel')
    }, items.length ? items.map(this.renderSearchRow) : React.createElement("div", {
      className: this.addPrefix('none')
    }, locale.noResultsText));
  };

  _proto.renderDropdownMenu = function renderDropdownMenu() {
    var _this$state2 = this.state,
        items = _this$state2.items,
        tempActivePaths = _this$state2.tempActivePaths,
        activePaths = _this$state2.activePaths,
        searchKeyword = _this$state2.searchKeyword;
    var _this$props6 = this.props,
        renderMenu = _this$props6.renderMenu,
        placement = _this$props6.placement,
        renderExtraFooter = _this$props6.renderExtraFooter,
        menuClassName = _this$props6.menuClassName,
        menuStyle = _this$props6.menuStyle,
        searchable = _this$props6.searchable,
        locale = _this$props6.locale;
    var classes = (0, _classnames.default)(this.addPrefix('cascader-menu'), this.addPrefix("placement-" + (0, _kebabCase2.default)(placement)), menuClassName);
    var menuProps = (0, _pick2.default)(this.props, _DropdownMenu.default.handledProps.filter(function (name) {
      return name !== 'classPrefix';
    }));
    return React.createElement(_picker.MenuWrapper, {
      className: classes,
      style: menuStyle
    }, searchable && React.createElement(_picker.SearchBar, {
      placeholder: locale.searchPlaceholder,
      onChange: this.handleSearch,
      value: searchKeyword
    }), React.createElement(_DropdownMenu.default, (0, _extends3.default)({}, menuProps, {
      classPrefix: this.addPrefix('cascader-menu'),
      ref: this.bindMenuContainerRef,
      cascadeItems: items,
      cascadePathItems: tempActivePaths || activePaths,
      activeItemValue: this.getValue(),
      onSelect: this.handleSelect,
      renderMenu: renderMenu
    })), renderExtraFooter && renderExtraFooter());
  };

  _proto.render = function render() {
    var _this$props7 = this.props,
        valueKey = _this$props7.valueKey,
        labelKey = _this$props7.labelKey,
        placeholder = _this$props7.placeholder,
        renderValue = _this$props7.renderValue,
        disabled = _this$props7.disabled,
        cleanable = _this$props7.cleanable,
        locale = _this$props7.locale,
        toggleComponentClass = _this$props7.toggleComponentClass,
        style = _this$props7.style,
        onEnter = _this$props7.onEnter,
        onExited = _this$props7.onExited,
        onClean = _this$props7.onClean,
        rest = (0, _objectWithoutPropertiesLoose2.default)(_this$props7, ["valueKey", "labelKey", "placeholder", "renderValue", "disabled", "cleanable", "locale", "toggleComponentClass", "style", "onEnter", "onExited", "onClean"]);
    var _this$state3 = this.state,
        activePaths = _this$state3.activePaths,
        active = _this$state3.active;
    var unhandled = (0, _utils2.getUnhandledProps)(Dropdown, rest);
    var value = this.getValue();
    var hasValue = !!value;
    var activeItemLabel = placeholder;

    if (activePaths.length > 0) {
      activeItemLabel = [];
      activePaths.forEach(function (item, index) {
        var key = item[valueKey] || item[labelKey];
        activeItemLabel.push(React.createElement("span", {
          key: key
        }, item[labelKey]));

        if (index < activePaths.length - 1) {
          activeItemLabel.push(React.createElement("span", {
            className: "separator",
            key: key + "-separator"
          }, ' / '));
        }
      });

      if (renderValue) {
        activeItemLabel = renderValue(value, activePaths, activeItemLabel);
      }
    }

    var classes = (0, _picker.getToggleWrapperClassName)('cascader', this.addPrefix, this.props, hasValue);
    return React.createElement(_rsuiteIntl.IntlProvider, {
      locale: locale
    }, React.createElement("div", {
      className: classes,
      style: style,
      tabIndex: -1,
      role: "menu",
      ref: this.bindContainerRef
    }, React.createElement(_picker.PickerToggleTrigger, {
      pickerProps: this.props,
      innerRef: this.bindTriggerRef,
      onEnter: (0, _utils2.createChainedFunction)(this.handleEntered, onEnter),
      onExit: (0, _utils2.createChainedFunction)(this.handleExit, onExited),
      speaker: this.renderDropdownMenu()
    }, React.createElement(_picker.PickerToggle, (0, _extends3.default)({}, unhandled, {
      componentClass: toggleComponentClass,
      onClean: (0, _utils2.createChainedFunction)(this.handleClean, onClean),
      cleanable: cleanable && !disabled,
      hasValue: hasValue,
      active: active
    }), activeItemLabel || React.createElement(_rsuiteIntl.FormattedMessage, {
      id: "placeholder"
    })))));
  };

  return Dropdown;
}(React.Component);

(0, _defineProperty2.default)(Dropdown, "defaultProps", {
  appearance: 'default',
  data: [],
  disabledItemValues: [],
  childrenKey: 'children',
  valueKey: 'value',
  labelKey: 'label',
  locale: {
    placeholder: 'Select',
    searchPlaceholder: 'Search',
    noResultsText: 'No results found'
  },
  cleanable: true,
  searchable: true,
  placement: 'bottomLeft'
});
(0, _defineProperty2.default)(Dropdown, "handledProps", ["appearance", "block", "childrenKey", "className", "classPrefix", "cleanable", "container", "containerPadding", "data", "defaultOpen", "defaultValue", "disabled", "disabledItemValues", "labelKey", "locale", "menuClassName", "menuHeight", "menuStyle", "menuWidth", "onChange", "onClean", "onClose", "onEnter", "onEntered", "onEntering", "onExit", "onExited", "onExiting", "onHide", "onOpen", "onSearch", "onSelect", "open", "placeholder", "placement", "renderExtraFooter", "renderMenu", "renderMenuItem", "renderValue", "searchable", "style", "toggleComponentClass", "value", "valueKey"]);
(0, _reactLifecyclesCompat.polyfill)(Dropdown);
var enhance = (0, _utils2.defaultProps)({
  classPrefix: 'picker'
});

var _default = enhance(Dropdown);

exports.default = _default;