import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
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";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import debounce from 'lodash.debounce';
import match from 'autosuggest-highlight/match';
import parse from 'autosuggest-highlight/parse';
import DropdownMenu from '../dropdownMenu';
import Input from '../input';
import Menu, { MenuItem } from '../menu';

function defaultFilter() {
  var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  var suggestions = arguments.length > 1 ? arguments[1] : undefined;
  var max = arguments.length > 2 ? arguments[2] : undefined;
  var inputValue = value.trim().toLowerCase();
  var inputLength = inputValue.length;
  var count = 0;
  return inputLength === 0 ? [] : suggestions.filter(function (suggestion) {
    var keep = count < max && suggestion.toLowerCase().indexOf(inputValue) > -1;

    if (keep) {
      count += 1;
    }

    return keep;
  });
}

var AutoComplete =
/*#__PURE__*/
function (_Component) {
  _inherits(AutoComplete, _Component);

  function AutoComplete(props) {
    var _this;

    _classCallCheck(this, AutoComplete);

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

    _defineProperty(_assertThisInitialized(_this), "width", 187);

    _defineProperty(_assertThisInitialized(_this), "getEl", function (el) {
      var inputRef = _this.props.inputRef;
      _this.el = el;
      inputRef && inputRef(el);
    });

    _defineProperty(_assertThisInitialized(_this), "handleOpen", function (isOpen) {
      var search = _this.state.search;

      if (_this.el) {
        var _this$el$getBoundingC = _this.el.getBoundingClientRect(),
            width = _this$el$getBoundingC.width;

        _this.width = width;
      }

      if (isOpen) {
        _this.getSuggestions(search);
      } else {
        _this.handleBlur();
      }

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

    _defineProperty(_assertThisInitialized(_this), "getSuggestions", debounce(function (value) {
      var _this$props = _this.props,
          filter = _this$props.filter,
          suggestions = _this$props.suggestions,
          maximumDisplayingSuggestions = _this$props.maximumDisplayingSuggestions,
          selectOnly = _this$props.selectOnly;

      if (selectOnly && !value) {
        return _this.setState({
          matches: suggestions
        });
      }

      var result = filter(value, suggestions, maximumDisplayingSuggestions);

      if (Array.isArray(result)) {
        _this.setState({
          matches: result
        });
      } else if (result.then && result.catch) {
        result.then(function (matches) {
          _this.setState({
            matches: matches
          });
        });
      }
    }, _this.props.waitTime, {
      maxWait: 2000
    }));

    _defineProperty(_assertThisInitialized(_this), "handleChange", function (isInput) {
      return function (arg0, arg1) {
        var _this$props2 = _this.props,
            onChange = _this$props2.onChange,
            selectOnly = _this$props2.selectOnly;
        var newValue;

        if (arg0 && arg0.preventDefault && arg0.target) {
          if (arg1) {
            newValue = arg1;
          } else if (arg0.target.nodeName === 'INPUT' || arg0.target.nodeName === 'TEXTAREA') {
            newValue = arg0.target.value;
          }
        } else {
          newValue = arg0;
        }

        if (isInput && selectOnly) {
          _this.setState({
            search: newValue
          });
        } else {
          _this.setState({
            value: newValue,
            search: newValue
          });

          onChange && onChange(newValue);
        }

        _this.getSuggestions(newValue);
      };
    });

    _defineProperty(_assertThisInitialized(_this), "handleSearch", function () {
      var onSearch = _this.props.onSearch;

      _this.handleChange(true).apply(void 0, arguments);

      if (onSearch) {
        onSearch.apply(void 0, arguments);
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handleSelect", function () {
      _this.handleChange(false).apply(void 0, arguments);

      var onSelect = _this.props.onSelect;

      if (onSelect) {
        onSelect.apply(void 0, arguments);
      }
    });

    _defineProperty(_assertThisInitialized(_this), "handleBlur", function () {
      _this.setState(function (state) {
        return {
          search: state.value
        };
      });
    });

    var defaultValue = props.defaultValue != null ? props.defaultValue : props.children.props.defaultValue;
    _this.state = {
      value: !props.selectOnly || props.suggestions.includes(defaultValue) ? defaultValue : '',
      search: defaultValue,
      matches: [],
      isOpen: false
    };
    return _this;
  }

  _createClass(AutoComplete, [{
    key: "componentWillReceiveProps",
    value: function componentWillReceiveProps(newProps) {
      if (newProps.defaultValue !== this.props.defaultValue) {
        this.setState({
          value: !newProps.selectOnly || newProps.suggestions.includes(newProps.defaultValue) ? newProps.defaultValue : '',
          search: newProps.defaultValue
        });
      }
    }
  }, {
    key: "suggestionsRender",
    value: function suggestionsRender(suggestion, value) {
      var _this$props3 = this.props,
          matchHighlight = _this$props3.matchHighlight,
          itemRender = _this$props3.itemRender;

      if (itemRender) {
        return itemRender(value, suggestion);
      }

      if (!matchHighlight) {
        return React.createElement(MenuItem, {
          value: suggestion,
          role: "option",
          key: suggestion
        }, suggestion);
      }

      var matches = match(suggestion, value);
      var parts = parse(suggestion, matches);
      return React.createElement(MenuItem, {
        value: suggestion,
        role: "option",
        key: suggestion
      }, parts.map(function (part, index) {
        return part.highlight ? React.createElement("strong", {
          key: String(index)
        }, part.text) : React.createElement("span", {
          key: String(index)
        }, part.text);
      }));
    }
  }, {
    key: "render",
    value: function render() {
      var _this2 = this;

      var _this$props4 = this.props,
          children = _this$props4.children,
          prefixCls = _this$props4.prefixCls,
          options = _this$props4.options,
          matchWidth = _this$props4.matchWidth,
          selectOnly = _this$props4.selectOnly,
          defaultValue = _this$props4.defaultValue,
          matchHighlight = _this$props4.matchHighlight,
          fullWidth = _this$props4.fullWidth,
          placeholder = _this$props4.placeholder,
          status = _this$props4.status,
          errorIcon = _this$props4.errorIcon,
          loadingIcon = _this$props4.loadingIcon,
          successIcon = _this$props4.successIcon,
          showStatusIcon = _this$props4.showStatusIcon,
          indent = _this$props4.indent,
          other = _objectWithoutProperties(_this$props4, ["children", "prefixCls", "options", "matchWidth", "selectOnly", "defaultValue", "matchHighlight", "fullWidth", "placeholder", "status", "errorIcon", "loadingIcon", "successIcon", "showStatusIcon", "indent"]);

      var _this$state = this.state,
          matches = _this$state.matches,
          search = _this$state.search,
          isOpen = _this$state.isOpen;
      var input = React.createElement(Input, {
        status: status,
        errorIcon: errorIcon,
        loadingIcon: loadingIcon,
        successIcon: successIcon,
        showStatusIcon: showStatusIcon,
        fullWidth: fullWidth,
        placeholder: placeholder,
        value: search,
        onChange: function onChange() {
          _this2.handleSearch.apply(_this2, arguments);
        },
        autoComplete: "off"
      });
      var menuStyle = matchWidth ? {
        width: "".concat(this.width, "px")
      } : {};
      return React.createElement("div", {
        className: prefixCls,
        ref: this.getEl,
        role: "combobox",
        "aria-autocomplete": "list",
        "aria-expanded": isOpen,
        "aria-haspopup": isOpen
      }, React.createElement(DropdownMenu, _extends({
        selectable: selectOnly
      }, other, {
        anchorEl: input,
        onSelect: this.handleSelect,
        onOpenChange: this.handleOpen,
        trigger: "focus"
      }), React.createElement(Menu, {
        className: classNames("".concat(prefixCls, "-menu")),
        role: "listbox",
        style: menuStyle,
        indent: indent
      }, options || matches.map(function (suggestion) {
        return _this2.suggestionsRender(suggestion, search);
      }))));
    }
  }]);

  return AutoComplete;
}(Component);

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

_defineProperty(AutoComplete, "propTypes", {
  prefixCls: PropTypes.string,
  inputRef: PropTypes.func,

  /** 备选的建议列表 */
  suggestions: PropTypes.array,

  /** 显示的建议数目最大值 */
  maximumDisplayingSuggestions: PropTypes.number,

  /** 自定义建议项根据输入值的算法 function(value, suggestions, maximumDisplayingSuggestions) */
  filter: PropTypes.func,

  /** 显示建议延迟时间（单位：ms） */
  waitTime: PropTypes.number,

  /** 建议项渲染方法 function(value, suggestion ) => item: ReactNode */
  itemRender: PropTypes.func,

  /** 输入框输入时回调 function(event) */
  onSearch: PropTypes.func,

  /** 选中建议项，或 input 的 value 变化时回调 function(value) */
  onChange: PropTypes.func,

  /** 是否只允许从建议列表里选择 */
  selectOnly: PropTypes.bool,

  /** 建议列表是否和输入框同宽 */
  matchWidth: PropTypes.bool,

  /** 是否高亮关键字 */
  matchHighlight: PropTypes.bool,

  /**
   * 是否占满整行
   */
  fullWidth: PropTypes.bool,

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

  /**
   * @ignore
   * 菜单缩进距离
   */
  indent: PropTypes.number
});

_defineProperty(AutoComplete, "defaultProps", {
  selectOnly: false,
  matchWidth: true,
  prefixCls: 'ne-auto-complete',
  suggestions: [],
  filter: defaultFilter,
  maximumDisplayingSuggestions: 5,
  waitTime: 200,
  matchHighlight: true,
  fullWidth: false,
  placeholder: '',
  indent: 6
});

export { AutoComplete as default };