import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
import _inherits from 'babel-runtime/helpers/inherits';
import _extends from 'babel-runtime/helpers/extends';
import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import KeyCode from 'rc-util/es/KeyCode';
import classnames from 'classnames';
import assign from 'object-assign';
import Animate from 'rc-animate';
import { getPropValue, getValuePropValue, /* isCombobox,*/
isMultipleOrTags, isMultipleOrTagsOrCombobox, isSingleMode, toArray, UNSELECTABLE_ATTRIBUTE, UNSELECTABLE_STYLE, preventDefaultEvent, getTreeNodesStates, flatToHierarchy, filterParentPosition, isInclude, labelCompatible, loopAllChildren, filterAllCheckedData, processSimpleTreeData } from './util';
import SelectTrigger from './SelectTrigger';
import _TreeNode from './TreeNode';
import { SHOW_ALL, SHOW_PARENT, SHOW_CHILD } from './strategies';
import { SelectPropTypes } from './PropTypes';

function noop() {}

function filterFn(input, child) {
  return String(getPropValue(child, labelCompatible(this.props.treeNodeFilterProp))).indexOf(input) > -1;
}

function saveRef(name, component) {
  this[name] = component;
}

function loopTreeData(data) {
  var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

  return data.map(function (item, index) {
    var pos = level + '-' + index;

    var label = item.label,
        value = item.value,
        disabled = item.disabled,
        key = item.key,
        hasOwnProperty = item.hasOwnProperty,
        selectable = item.selectable,
        children = item.children,
        isLeaf = item.isLeaf,
        otherProps = _objectWithoutProperties(item, ['label', 'value', 'disabled', 'key', 'hasOwnProperty', 'selectable', 'children', 'isLeaf']);

    var props = _extends({
      value: value,
      title: label,
      // value: value || String(key || label), // cause onChange callback error
      key: key || value || pos,
      disabled: disabled || false,
      selectable: selectable === false ? selectable : true
    }, otherProps);
    var ret = void 0;
    if (children && children.length) {
      ret = React.createElement(
        _TreeNode,
        props,
        loopTreeData(children, pos)
      );
    } else {
      ret = React.createElement(_TreeNode, _extends({}, props, { isLeaf: isLeaf }));
    }
    return ret;
  });
}

var Select = function (_Component) {
  _inherits(Select, _Component);

  function Select(props) {
    _classCallCheck(this, Select);

    var _this = _possibleConstructorReturn(this, _Component.call(this, props));

    _initialiseProps.call(_this);

    var value = [];
    if ('value' in props) {
      value = toArray(props.value);
    } else {
      value = toArray(props.defaultValue);
    }
    // save parsed treeData, for performance (treeData may be very big)
    _this.renderedTreeData = _this.renderTreeData();
    value = _this.addLabelToValue(props, value);
    value = _this.getValue(props, value, props.inputValue ? '__strict' : true);
    var inputValue = props.inputValue || '';
    // if (props.combobox) {
    //   inputValue = value.length ? String(value[0].value) : '';
    // }
    _this.saveInputRef = saveRef.bind(_this, 'inputInstance');
    _this.saveInputMirrorRef = saveRef.bind(_this, 'inputMirrorInstance');
    _this.state = {
      value: value,
      inputValue: inputValue,
      open: props.open || props.defaultOpen,
      focused: false
    };
    return _this;
  }

  Select.prototype.componentDidMount = function componentDidMount() {
    if (isMultipleOrTags(this.props)) {
      var inputNode = this.getInputDOMNode();
      if (inputNode.value) {
        inputNode.style.width = '';
        inputNode.style.width = this.inputMirrorInstance.clientWidth + 'px';
      } else {
        inputNode.style.width = '';
      }
    }
  };

  Select.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
    // save parsed treeData, for performance (treeData may be very big)
    this.renderedTreeData = this.renderTreeData(nextProps);
    // Detecting whether the object of `onChange`'s argument  is old ref.
    // Better to do a deep equal later.
    this._cacheTreeNodesStates = this._cacheTreeNodesStates !== 'no' && this._savedValue && nextProps.value === this._savedValue;
    if (this.props.treeData !== nextProps.treeData || this.props.children !== nextProps.children) {
      // refresh this._treeNodesStates cache
      this._treeNodesStates = getTreeNodesStates(this.renderedTreeData || nextProps.children, this.state.value.map(function (item) {
        return item.value;
      }));
    }
    if ('value' in nextProps) {
      var value = toArray(nextProps.value);
      value = this.addLabelToValue(nextProps, value);
      value = this.getValue(nextProps, value);
      this.setState({
        value: value
      });
      // if (nextProps.combobox) {
      //   this.setState({
      //     inputValue: value.length ? String(value[0].key) : '',
      //   });
      // }
    }
    if (nextProps.inputValue !== this.props.inputValue) {
      this.setState({
        inputValue: nextProps.inputValue
      });
    }
    if ('open' in nextProps) {
      this.setState({
        open: nextProps.open
      });
    }
  };

  Select.prototype.componentWillUpdate = function componentWillUpdate(nextProps) {
    if (this._savedValue && nextProps.value && nextProps.value !== this._savedValue && nextProps.value === this.props.value) {
      this._cacheTreeNodesStates = false;
      this.getValue(nextProps, this.addLabelToValue(nextProps, toArray(nextProps.value)));
    }
  };

  Select.prototype.componentDidUpdate = function componentDidUpdate() {
    var state = this.state;
    var props = this.props;
    if (state.open && isMultipleOrTags(props)) {
      var inputNode = this.getInputDOMNode();
      if (inputNode.value) {
        inputNode.style.width = '';
        inputNode.style.width = this.inputMirrorInstance.clientWidth + 'px';
      } else {
        inputNode.style.width = '';
      }
    }
  };

  Select.prototype.componentWillUnmount = function componentWillUnmount() {
    this.clearDelayTimer();
    if (this.dropdownContainer) {
      ReactDOM.unmountComponentAtNode(this.dropdownContainer);
      document.body.removeChild(this.dropdownContainer);
      this.dropdownContainer = null;
    }
  };

  // combobox ignore


  Select.prototype.getLabelFromNode = function getLabelFromNode(child) {
    return getPropValue(child, this.props.treeNodeLabelProp);
  };

  Select.prototype.getLabelFromProps = function getLabelFromProps(props, value) {
    var _this2 = this;

    if (value === undefined) {
      return null;
    }
    var label = null;
    loopAllChildren(this.renderedTreeData || props.children, function (item) {
      if (getValuePropValue(item) === value) {
        label = _this2.getLabelFromNode(item);
      }
    });
    if (label === null) {
      return value;
    }
    return label;
  };

  Select.prototype.getDropdownContainer = function getDropdownContainer() {
    if (!this.dropdownContainer) {
      this.dropdownContainer = document.createElement('div');
      document.body.appendChild(this.dropdownContainer);
    }
    return this.dropdownContainer;
  };

  Select.prototype.getSearchPlaceholderElement = function getSearchPlaceholderElement(hidden) {
    var props = this.props;
    var placeholder = void 0;
    if (isMultipleOrTagsOrCombobox(props)) {
      placeholder = props.placeholder || props.searchPlaceholder;
    } else {
      placeholder = props.searchPlaceholder;
    }
    if (placeholder) {
      return React.createElement(
        'span',
        {
          style: { display: hidden ? 'none' : 'block' },
          onClick: this.onPlaceholderClick,
          className: props.prefixCls + '-search__field__placeholder'
        },
        placeholder
      );
    }
    return null;
  };

  Select.prototype.getInputElement = function getInputElement() {
    var inputValue = this.state.inputValue;
    var _props2 = this.props,
        prefixCls = _props2.prefixCls,
        disabled = _props2.disabled;

    return React.createElement(
      'span',
      { className: prefixCls + '-search__field__wrap' },
      React.createElement('input', {
        ref: this.saveInputRef,
        onChange: this.onInputChange,
        onKeyDown: this.onInputKeyDown,
        value: inputValue,
        disabled: disabled,
        className: prefixCls + '-search__field',
        role: 'textbox'
      }),
      React.createElement(
        'span',
        {
          ref: this.saveInputMirrorRef,
          className: prefixCls + '-search__field__mirror'
        },
        inputValue,
        '\xA0'
      ),
      isMultipleOrTags(this.props) ? null : this.getSearchPlaceholderElement(!!inputValue)
    );
  };

  Select.prototype.getInputDOMNode = function getInputDOMNode() {
    return this.inputInstance;
  };

  Select.prototype.getPopupDOMNode = function getPopupDOMNode() {
    return this.refs.trigger.getPopupDOMNode();
  };

  Select.prototype.getPopupComponentRefs = function getPopupComponentRefs() {
    return this.refs.trigger.getPopupEleRefs();
  };

  Select.prototype.getValue = function getValue(_props, val) {
    var _this3 = this;

    var init = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;

    var value = val;
    // if inputValue existing, tree is checkStrictly
    var _strict = init === '__strict' || init && (this.state && this.state.inputValue || this.props.inputValue !== _props.inputValue);
    if (_props.treeCheckable && (_props.treeCheckStrictly || _strict)) {
      this.halfCheckedValues = [];
      value = [];
      val.forEach(function (i) {
        if (!i.halfChecked) {
          value.push(i);
        } else {
          _this3.halfCheckedValues.push(i);
        }
      });
    }
    // if (!(_props.treeCheckable && !_props.treeCheckStrictly)) {
    if (!!!_props.treeCheckable || _props.treeCheckable && (_props.treeCheckStrictly || _strict)) {
      return value;
    }
    var checkedTreeNodes = void 0;
    if (this._cachetreeData && this._cacheTreeNodesStates && this._checkedNodes && this.state && !this.state.inputValue) {
      this.checkedTreeNodes = checkedTreeNodes = this._checkedNodes;
    } else {
      /**
       * Note: `this._treeNodesStates`'s treeNodesStates must correspond to nodes of the
       * final tree (`processTreeNode` function from SelectTrigger.jsx produce the final tree).
       *
       * And, `this._treeNodesStates` from `onSelect` is previous value,
       * so it perhaps only have a few nodes, but the newly filtered tree can have many nodes,
       * thus, you cannot use previous _treeNodesStates.
       */
      // getTreeNodesStates is not effective.
      this._treeNodesStates = getTreeNodesStates(this.renderedTreeData || _props.children, value.map(function (item) {
        return item.value;
      }));
      this.checkedTreeNodes = checkedTreeNodes = this._treeNodesStates.checkedNodes;
    }
    var mapLabVal = function mapLabVal(arr) {
      return arr.map(function (itemObj) {
        return {
          value: getValuePropValue(itemObj.node),
          label: getPropValue(itemObj.node, _props.treeNodeLabelProp)
        };
      });
    };
    var props = this.props;
    var checkedValues = [];
    if (props.showCheckedStrategy === SHOW_ALL) {
      checkedValues = mapLabVal(checkedTreeNodes);
    } else if (props.showCheckedStrategy === SHOW_PARENT) {
      var posArr = filterParentPosition(checkedTreeNodes.map(function (itemObj) {
        return itemObj.pos;
      }));
      checkedValues = mapLabVal(checkedTreeNodes.filter(function (itemObj) {
        return posArr.indexOf(itemObj.pos) !== -1;
      }));
    } else {
      checkedValues = mapLabVal(checkedTreeNodes.filter(function (itemObj) {
        return !itemObj.node.props.children;
      }));
    }
    return checkedValues;
  };

  Select.prototype.getCheckedNodes = function getCheckedNodes(info, props) {
    // TODO treeCheckable does not support tags/dynamic
    var checkedNodes = info.checkedNodes;
    // if inputValue existing, tree is checkStrictly

    if (props.treeCheckStrictly || this.state.inputValue) {
      return checkedNodes;
    }
    var checkedNodesPositions = info.checkedNodesPositions;
    if (props.showCheckedStrategy === SHOW_ALL) {
      checkedNodes = checkedNodes;
    } else if (props.showCheckedStrategy === SHOW_PARENT) {
      var posArr = filterParentPosition(checkedNodesPositions.map(function (itemObj) {
        return itemObj.pos;
      }));
      checkedNodes = checkedNodesPositions.filter(function (itemObj) {
        return posArr.indexOf(itemObj.pos) !== -1;
      }).map(function (itemObj) {
        return itemObj.node;
      });
    } else {
      checkedNodes = checkedNodes.filter(function (n) {
        return !n.props.children;
      });
    }
    return checkedNodes;
  };

  Select.prototype.getDeselectedValue = function getDeselectedValue(selectedValue) {
    var checkedTreeNodes = this.checkedTreeNodes;
    var unCheckPos = void 0;
    checkedTreeNodes.forEach(function (itemObj) {
      if (itemObj.node.props.value === selectedValue) {
        unCheckPos = itemObj.pos;
      }
    });
    var nArr = unCheckPos && unCheckPos.split('-');
    var newVals = [];
    var newCkTns = [];
    checkedTreeNodes.forEach(function (itemObj) {
      var iArr = itemObj.pos.split('-');
      if (itemObj.pos === unCheckPos || nArr.length > iArr.length && isInclude(iArr, nArr) || nArr.length < iArr.length && isInclude(nArr, iArr)) {
        // Filter ancestral and children nodes when uncheck a node.
        return;
      }
      newCkTns.push(itemObj);
      newVals.push(itemObj.node.props.value);
    });
    this.checkedTreeNodes = this._checkedNodes = newCkTns;
    var nv = this.state.value.filter(function (val) {
      return newVals.indexOf(val.value) !== -1;
    });
    this.fireChange(nv, { triggerValue: selectedValue, clear: true });
  };

  Select.prototype.setOpenState = function setOpenState(open, needFocus) {
    var _this4 = this;

    var documentClickClose = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

    this.clearDelayTimer();
    var props = this.props,
        refs = this.refs;
    // can not optimize, if children is empty
    // if (this.state.open === open) {
    //   return;
    // }

    if (!this.props.onDropdownVisibleChange(open, { documentClickClose: documentClickClose })) {
      return;
    }
    this.setState({
      open: open
    }, function () {
      if (needFocus || open) {
        if (open || isMultipleOrTagsOrCombobox(props)) {
          var input = _this4.getInputDOMNode();
          if (input && document.activeElement !== input) {
            input.focus();
          }
        } else if (refs.selection) {
          refs.selection.focus();
        }
      }
    });
  };

  Select.prototype.clearSearchInput = function clearSearchInput() {
    this.getInputDOMNode().focus();
    if (!('inputValue' in this.props)) {
      this.setState({ inputValue: '' });
    }
  };

  Select.prototype.addLabelToValue = function addLabelToValue(props, value_) {
    var _this5 = this;

    var value = value_;
    if (this.isLabelInValue()) {
      value.forEach(function (v, i) {
        if (Object.prototype.toString.call(value[i]) !== '[object Object]') {
          value[i] = {
            value: '',
            label: ''
          };
          return;
        }
        v.label = v.label || _this5.getLabelFromProps(props, v.value);
      });
    } else {
      value = value.map(function (v) {
        return {
          value: v,
          label: _this5.getLabelFromProps(props, v)
        };
      });
    }
    return value;
  };

  Select.prototype.clearDelayTimer = function clearDelayTimer() {
    if (this.delayTimer) {
      clearTimeout(this.delayTimer);
      this.delayTimer = null;
    }
  };

  Select.prototype.removeSelected = function removeSelected(selectedVal) {
    var props = this.props;
    if (props.disabled) {
      return;
    }
    this._cacheTreeNodesStates = 'no';
    if (props.treeCheckable && (props.showCheckedStrategy === SHOW_ALL || props.showCheckedStrategy === SHOW_PARENT) && !(props.treeCheckStrictly || this.state.inputValue)) {
      this.getDeselectedValue(selectedVal);
      return;
    }
    // click the node's `x`(in select box), likely trigger the TreeNode's `unCheck` event,
    // cautiously, they are completely different, think about it, the tree may not render at first,
    // but the nodes in select box are ready.
    var label = void 0;
    var value = this.state.value.filter(function (singleValue) {
      if (singleValue.value === selectedVal) {
        label = singleValue.label;
      }
      return singleValue.value !== selectedVal;
    });
    var canMultiple = isMultipleOrTags(props);

    if (canMultiple) {
      var event = selectedVal;
      if (this.isLabelInValue()) {
        event = {
          value: selectedVal,
          label: label
        };
      }
      props.onDeselect(event);
    }
    if (props.treeCheckable) {
      if (this.checkedTreeNodes && this.checkedTreeNodes.length) {
        this.checkedTreeNodes = this._checkedNodes = this.checkedTreeNodes.filter(function (item) {
          return value.some(function (i) {
            return i.value === item.node.props.value;
          });
        });
      }
    }
    this.fireChange(value, { triggerValue: selectedVal, clear: true });
  };

  Select.prototype.openIfHasChildren = function openIfHasChildren() {
    var props = this.props;
    if (React.Children.count(props.children) || isSingleMode(props)) {
      this.setOpenState(true);
    }
  };

  Select.prototype.fireChange = function fireChange(value, extraInfo) {
    var _this6 = this;

    var props = this.props;
    var vals = value.map(function (i) {
      return i.value;
    });
    var sv = this.state.value.map(function (i) {
      return i.value;
    });
    if (vals.length !== sv.length || !vals.every(function (val, index) {
      return sv[index] === val;
    })) {
      var ex = { preValue: [].concat(this.state.value) };
      if (extraInfo) {
        assign(ex, extraInfo);
      }
      var labs = null;
      var vls = value;
      if (!this.isLabelInValue()) {
        labs = value.map(function (i) {
          return i.label;
        });
        vls = vls.map(function (v) {
          return v.value;
        });
      } else if (this.halfCheckedValues && this.halfCheckedValues.length) {
        this.halfCheckedValues.forEach(function (i) {
          if (!vls.some(function (v) {
            return v.value === i.value;
          })) {
            vls.push(i);
          }
        });
      }
      if (props.treeCheckable && ex.clear) {
        var treeData = this.renderedTreeData || props.children;
        ex.allCheckedNodes = flatToHierarchy(filterAllCheckedData(vals, treeData));
      }
      if (props.treeCheckable && this.state.inputValue) {
        var _vls = [].concat(this.state.value);
        if (ex.checked) {
          value.forEach(function (i) {
            if (_vls.every(function (ii) {
              return ii.value !== i.value;
            })) {
              _vls.push(_extends({}, i));
            }
          });
        } else {
          var index = void 0;
          var includeVal = _vls.some(function (i, ind) {
            if (i.value === ex.triggerValue) {
              index = ind;
              return true;
            }
          });
          if (includeVal) {
            _vls.splice(index, 1);
          }
        }
        vls = _vls;
        if (!this.isLabelInValue()) {
          labs = _vls.map(function (v) {
            return v.label;
          });
          vls = _vls.map(function (v) {
            return v.value;
          });
        }
      }
      this._savedValue = isMultipleOrTags(props) ? vls : vls[0];
      props.onChange(this._savedValue, labs, ex);
      if (!('value' in props)) {
        this._cacheTreeNodesStates = false;
        this.setState({
          value: this.getValue(props, toArray(this._savedValue).map(function (v, i) {
            return _this6.isLabelInValue() ? v : {
              value: v,
              label: labs && labs[i]
            };
          }))
        });
      }
    }
  };

  Select.prototype.isLabelInValue = function isLabelInValue() {
    var _props3 = this.props,
        treeCheckable = _props3.treeCheckable,
        treeCheckStrictly = _props3.treeCheckStrictly,
        labelInValue = _props3.labelInValue;

    if (treeCheckable && treeCheckStrictly) {
      return true;
    }
    return labelInValue || false;
  };

  Select.prototype.renderTopControlNode = function renderTopControlNode() {
    var _this7 = this;

    var value = this.state.value;

    var props = this.props;
    var choiceTransitionName = props.choiceTransitionName,
        prefixCls = props.prefixCls,
        maxTagTextLength = props.maxTagTextLength;
    // single and not combobox, input is inside dropdown

    if (isSingleMode(props)) {
      var innerNode = React.createElement(
        'span',
        {
          key: 'placeholder',
          className: prefixCls + '-selection__placeholder'
        },
        props.placeholder
      );
      if (value.length) {
        innerNode = React.createElement(
          'span',
          {
            key: 'value',
            title: value[0].label,
            className: prefixCls + '-selection-selected-value'
          },
          value[0].label
        );
      }
      return React.createElement(
        'span',
        { className: prefixCls + '-selection__rendered' },
        innerNode
      );
    }

    var selectedValueNodes = [];
    if (isMultipleOrTags(props)) {
      selectedValueNodes = value.map(function (singleValue) {
        var content = singleValue.label;
        var title = content;
        if (maxTagTextLength && typeof content === 'string' && content.length > maxTagTextLength) {
          content = content.slice(0, maxTagTextLength) + '...';
        }
        return React.createElement(
          'li',
          _extends({
            style: UNSELECTABLE_STYLE
          }, UNSELECTABLE_ATTRIBUTE, {
            onMouseDown: preventDefaultEvent,
            className: prefixCls + '-selection__choice',
            key: singleValue.value,
            title: title
          }),
          React.createElement('span', {
            className: prefixCls + '-selection__choice__remove',
            onClick: _this7.removeSelected.bind(_this7, singleValue.value)
          }),
          React.createElement(
            'span',
            { className: prefixCls + '-selection__choice__content' },
            content
          )
        );
      });
    }
    selectedValueNodes.push(React.createElement(
      'li',
      {
        className: prefixCls + '-search ' + prefixCls + '-search--inline',
        key: '__input'
      },
      this.getInputElement()
    ));
    var className = prefixCls + '-selection__rendered';
    if (isMultipleOrTags(props) && choiceTransitionName) {
      return React.createElement(
        Animate,
        {
          className: className,
          component: 'ul',
          transitionName: choiceTransitionName,
          onLeave: this.onChoiceAnimationLeave
        },
        selectedValueNodes
      );
    }
    return React.createElement(
      'ul',
      { className: className },
      selectedValueNodes
    );
  };

  Select.prototype.renderTreeData = function renderTreeData(props) {
    var validProps = props || this.props;
    if (validProps.treeData) {
      if (props && props.treeData === this.props.treeData && this.renderedTreeData) {
        // cache and use pre data.
        this._cachetreeData = true;
        return this.renderedTreeData;
      }
      this._cachetreeData = false;
      var treeData = [].concat(validProps.treeData);
      // process treeDataSimpleMode
      if (validProps.treeDataSimpleMode) {
        var simpleFormat = {
          id: 'id',
          pId: 'pId',
          rootPId: null
        };
        if (Object.prototype.toString.call(validProps.treeDataSimpleMode) === '[object Object]') {
          assign(simpleFormat, validProps.treeDataSimpleMode);
        }
        treeData = processSimpleTreeData(treeData, simpleFormat);
      }
      return loopTreeData(treeData);
    }
  };

  Select.prototype.render = function render() {
    var _rootCls;

    var props = this.props;
    var multiple = isMultipleOrTags(props);
    var state = this.state;
    var className = props.className,
        disabled = props.disabled,
        allowClear = props.allowClear,
        prefixCls = props.prefixCls;

    var ctrlNode = this.renderTopControlNode();
    var extraSelectionProps = {};
    if (!isMultipleOrTagsOrCombobox(props)) {
      extraSelectionProps = {
        onKeyDown: this.onKeyDown,
        tabIndex: 0
      };
    }
    var rootCls = (_rootCls = {}, _rootCls[className] = !!className, _rootCls[prefixCls] = 1, _rootCls[prefixCls + '-open'] = state.open, _rootCls[prefixCls + '-focused'] = state.open || state.focused, _rootCls[prefixCls + '-disabled'] = disabled, _rootCls[prefixCls + '-enabled'] = !disabled, _rootCls[prefixCls + '-allow-clear'] = !!props.allowClear, _rootCls);

    var clear = React.createElement('span', {
      key: 'clear',
      className: prefixCls + '-selection__clear',
      onClick: this.onClearSelection
    });
    return React.createElement(
      SelectTrigger,
      _extends({}, props, {
        treeNodes: props.children,
        treeData: this.renderedTreeData,
        _cachetreeData: this._cachetreeData,
        _treeNodesStates: this._treeNodesStates,
        halfCheckedValues: this.halfCheckedValues,
        multiple: multiple,
        disabled: disabled,
        visible: state.open,
        inputValue: state.inputValue,
        inputElement: this.getInputElement(),
        value: state.value,
        onDropdownVisibleChange: this.onDropdownVisibleChange,
        getPopupContainer: props.getPopupContainer,
        onSelect: this.onSelect,
        ref: 'trigger'
      }),
      React.createElement(
        'span',
        {
          style: props.style,
          onClick: props.onClick,
          className: classnames(rootCls)
        },
        React.createElement(
          'span',
          _extends({
            ref: 'selection',
            key: 'selection',
            className: prefixCls + '-selection\n            ' + prefixCls + '-selection--' + (multiple ? 'multiple' : 'single'),
            role: 'combobox',
            'aria-autocomplete': 'list',
            'aria-haspopup': 'true',
            'aria-expanded': state.open
          }, extraSelectionProps),
          ctrlNode,
          allowClear && this.state.value.length && this.state.value[0].value ? clear : null,
          multiple || !props.showArrow ? null : React.createElement(
            'span',
            {
              key: 'arrow',
              className: prefixCls + '-arrow',
              style: { outline: 'none' }
            },
            React.createElement('b', null)
          ),
          multiple ? this.getSearchPlaceholderElement(!!this.state.inputValue || this.state.value.length) : null
        )
      )
    );
  };

  return Select;
}(Component);

Select.propTypes = SelectPropTypes;
Select.defaultProps = {
  prefixCls: 'rc-tree-select',
  filterTreeNode: filterFn,
  showSearch: true,
  allowClear: false,
  placeholder: '',
  searchPlaceholder: '',
  labelInValue: false,
  onClick: noop,
  onChange: noop,
  onSelect: noop,
  onDeselect: noop,
  onSearch: noop,
  showArrow: true,
  dropdownMatchSelectWidth: true,
  dropdownStyle: {},
  onDropdownVisibleChange: function onDropdownVisibleChange() {
    return true;
  },
  notFoundContent: 'Not Found',
  showCheckedStrategy: SHOW_CHILD,
  // skipHandleInitValue: false, // Deprecated (use treeCheckStrictly)
  treeCheckStrictly: false,
  treeIcon: false,
  treeLine: false,
  treeDataSimpleMode: false,
  treeDefaultExpandAll: false,
  treeCheckable: false,
  treeNodeFilterProp: 'value',
  treeNodeLabelProp: 'title'
};

var _initialiseProps = function _initialiseProps() {
  var _this8 = this;

  this.onInputChange = function (event) {
    var val = event.target.value;
    var props = _this8.props;

    _this8.setState({
      inputValue: val,
      open: true
    });
    if (props.treeCheckable && !val) {
      _this8.setState({
        value: _this8.getValue(props, [].concat(_this8.state.value), false)
      });
    }
    props.onSearch(val);
  };

  this.onDropdownVisibleChange = function (open) {
    // selection inside combobox cause click
    if (!open && document.activeElement === _this8.getInputDOMNode()) {}
    // return;

    // this.setOpenState(open);
    // setTimeout, then have animation. why?
    setTimeout(function () {
      _this8.setOpenState(open, undefined, !open);
    }, 10);
  };

  this.onKeyDown = function (event) {
    var props = _this8.props;
    if (props.disabled) {
      return;
    }
    var keyCode = event.keyCode;
    if (_this8.state.open && !_this8.getInputDOMNode()) {
      _this8.onInputKeyDown(event);
    } else if (keyCode === KeyCode.ENTER || keyCode === KeyCode.DOWN) {
      _this8.setOpenState(true);
      event.preventDefault();
    }
  };

  this.onInputKeyDown = function (event) {
    var props = _this8.props;
    if (props.disabled) {
      return;
    }
    var state = _this8.state;
    var keyCode = event.keyCode;
    if (isMultipleOrTags(props) && !event.target.value && keyCode === KeyCode.BACKSPACE) {
      var value = state.value.concat();
      if (value.length) {
        var popValue = value.pop();
        _this8.removeSelected(_this8.isLabelInValue() ? popValue : popValue.value);
      }
      return;
    }
    if (keyCode === KeyCode.DOWN) {
      if (!state.open) {
        _this8.openIfHasChildren();
        event.preventDefault();
        event.stopPropagation();
        return;
      }
    } else if (keyCode === KeyCode.ESC) {
      if (state.open) {
        _this8.setOpenState(false);
        event.preventDefault();
        event.stopPropagation();
      }
      return;
    }
  };

  this.onSelect = function (selectedKeys, info) {
    if (info.selected === false) {
      _this8.onDeselect(info);
      return;
    }
    var item = info.node;
    var value = _this8.state.value;
    var props = _this8.props;
    var selectedValue = getValuePropValue(item);
    var selectedLabel = _this8.getLabelFromNode(item);
    var event = selectedValue;
    if (_this8.isLabelInValue()) {
      event = {
        value: event,
        label: selectedLabel
      };
    }
    props.onSelect(event, item, info);
    var checkEvt = info.event === 'check';
    if (isMultipleOrTags(props)) {
      _this8.clearSearchInput();
      if (checkEvt) {
        value = _this8.getCheckedNodes(info, props).map(function (n) {
          return {
            value: getValuePropValue(n),
            label: _this8.getLabelFromNode(n)
          };
        });
      } else {
        if (value.some(function (i) {
          return i.value === selectedValue;
        })) {
          return;
        }
        value = value.concat([{
          value: selectedValue,
          label: selectedLabel
        }]);
      }
    } else {
      if (value.length && value[0].value === selectedValue) {
        _this8.setOpenState(false);
        return;
      }
      value = [{
        value: selectedValue,
        label: selectedLabel
      }];
      _this8.setOpenState(false);
    }

    var extraInfo = {
      triggerValue: selectedValue,
      triggerNode: item
    };
    if (checkEvt) {
      extraInfo.checked = info.checked;
      // if inputValue existing, tree is checkStrictly
      extraInfo.allCheckedNodes = props.treeCheckStrictly || _this8.state.inputValue ? info.checkedNodes : flatToHierarchy(info.checkedNodesPositions);
      _this8._checkedNodes = info.checkedNodesPositions;
      var _tree = _this8.refs.trigger.popupEle;
      _this8._treeNodesStates = _tree.checkKeys;
    } else {
      extraInfo.selected = info.selected;
    }

    _this8.fireChange(value, extraInfo);
    if (props.inputValue === null) {
      _this8.setState({
        inputValue: ''
      });
    }
  };

  this.onDeselect = function (info) {
    _this8.removeSelected(getValuePropValue(info.node));
    if (!isMultipleOrTags(_this8.props)) {
      _this8.setOpenState(false);
    } else {
      _this8.clearSearchInput();
    }
  };

  this.onPlaceholderClick = function () {
    _this8.getInputDOMNode().focus();
  };

  this.onClearSelection = function (event) {
    var props = _this8.props;
    var state = _this8.state;
    if (props.disabled) {
      return;
    }
    event.stopPropagation();
    _this8._cacheTreeNodesStates = 'no';
    _this8._checkedNodes = [];
    if (state.inputValue || state.value.length) {
      _this8.setOpenState(false);
      if (typeof props.inputValue === 'undefined') {
        _this8.setState({
          inputValue: ''
        }, function () {
          _this8.fireChange([]);
        });
      } else {
        _this8.fireChange([]);
      }
    }
  };

  this.onChoiceAnimationLeave = function () {
    _this8.refs.trigger.refs.trigger.forcePopupAlign();
  };
};

Select.SHOW_ALL = SHOW_ALL;
Select.SHOW_PARENT = SHOW_PARENT;
Select.SHOW_CHILD = SHOW_CHILD;

export default Select;