import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _createClass from 'babel-runtime/helpers/createClass';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
import _inherits from 'babel-runtime/helpers/inherits';
var _jsxFileName = 'src/autoComplete/AutoComplete.jsx';
import React, { Component, cloneElement } from 'react';
import PropTypes from 'prop-types';
import Menu, { MenuItem } from '../menu';
import Input from '../input';
import DropdownMenu from '../dropdownMenu';
import classNames from 'classnames';
import debounce from 'lodash.debounce';
import match from 'autosuggest-highlight/match';
import parse from 'autosuggest-highlight/parse';

function defaultFilter() {
    var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
    var suggestions = arguments[1];
    var max = arguments[2];

    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().slice(0, inputLength) === inputValue;

        if (keep) {
            count += 1;
        }

        return keep;
    });
}

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

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

        var _this = _possibleConstructorReturn(this, (AutoComplete.__proto__ || Object.getPrototypeOf(AutoComplete)).call(this, props));

        _this.width = 187;

        _this.getEl = function (el) {
            var inputRef = _this.props.inputRef;

            _this.el = el;

            inputRef && inputRef(el);
        };

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

                _this.width = width;
                _this.setState({
                    width: width
                });
            }
            if (isOpen) {
                _this.getSuggestions(_this.state.search);
            } else {
                _this.handleBlur();
            }
            _this.setState({
                isOpen: isOpen
            });
        };

        _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
        });

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

                var newValue = void 0;
                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);
            };
        };

        _this.handleSearch = function () {
            _this.handleChange(true).apply(undefined, arguments);
            if (_this.props.onSearch) {
                var _this$props3;

                (_this$props3 = _this.props).onSearch.apply(_this$props3, arguments);
            }
        };

        _this.handleSelect = function () {
            _this.handleChange(false).apply(undefined, arguments);
            if (_this.props.onSelect) {
                var _this$props4;

                (_this$props4 = _this.props).onSelect.apply(_this$props4, arguments);
            }
        };

        _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 _this2 = this;

            var _props = this.props,
                matchHighlight = _props.matchHighlight,
                itemRender = _props.itemRender;

            if (itemRender) {
                return itemRender(value, suggestion);
            }
            if (!matchHighlight) {
                return React.createElement(
                    MenuItem,
                    { value: suggestion, role: 'option', key: suggestion, __source: {
                            fileName: _jsxFileName,
                            lineNumber: 123
                        },
                        __self: this
                    },
                    suggestion
                );
            }
            var matches = match(suggestion, value);
            var parts = parse(suggestion, matches);
            return React.createElement(
                MenuItem,
                { value: suggestion, role: 'option', key: suggestion, __source: {
                        fileName: _jsxFileName,
                        lineNumber: 131
                    },
                    __self: this
                },
                parts.map(function (part, index) {
                    return part.highlight ? React.createElement(
                        'strong',
                        { key: String(index), __source: {
                                fileName: _jsxFileName,
                                lineNumber: 134
                            },
                            __self: _this2
                        },
                        part.text
                    ) : React.createElement(
                        'span',
                        { key: String(index), __source: {
                                fileName: _jsxFileName,
                                lineNumber: 136
                            },
                            __self: _this2
                        },
                        part.text
                    );
                })
            );
        }
    }, {
        key: 'render',
        value: function render() {
            var _this3 = this;

            var _props2 = this.props,
                children = _props2.children,
                prefixCls = _props2.prefixCls,
                options = _props2.options,
                matchWidth = _props2.matchWidth,
                selectOnly = _props2.selectOnly,
                defaultValue = _props2.defaultValue,
                matchHighlight = _props2.matchHighlight,
                other = _objectWithoutProperties(_props2, ['children', 'prefixCls', 'options', 'matchWidth', 'selectOnly', 'defaultValue', 'matchHighlight']);

            var _state = this.state,
                matches = _state.matches,
                search = _state.search,
                isOpen = _state.isOpen;

            var input = React.createElement(Input, {
                value: search,
                onChange: function onChange() {
                    _this3.handleSearch.apply(_this3, arguments);
                },
                autoComplete: 'off',
                __source: {
                    fileName: _jsxFileName,
                    lineNumber: 229
                },
                __self: this
            });
            var menuStyle = matchWidth ? {
                width: this.width + 'px'
            } : {};
            return React.createElement(
                'div',
                {
                    className: prefixCls,
                    ref: this.getEl,
                    role: 'combobox',
                    'aria-autocomplete': 'list',
                    'aria-expanded': isOpen,
                    'aria-haspopup': isOpen, __source: {
                        fileName: _jsxFileName,
                        lineNumber: 243
                    },
                    __self: this
                },
                React.createElement(
                    DropdownMenu,
                    Object.assign({
                        selectable: selectOnly
                    }, other, {
                        anchorEl: input,
                        onSelect: this.handleSelect,
                        onOpenChange: this.handleOpen,
                        trigger: 'focus', __source: {
                            fileName: _jsxFileName,
                            lineNumber: 250
                        },
                        __self: this
                    }),
                    React.createElement(
                        Menu,
                        { className: classNames(prefixCls + '-menu'), role: 'listbox', style: menuStyle, __source: {
                                fileName: _jsxFileName,
                                lineNumber: 257
                            },
                            __self: this
                        },
                        options ? options : matches.map(function (suggestion) {
                            return _this3.suggestionsRender(suggestion, search);
                        })
                    )
                )
            );
        }
    }]);

    return AutoComplete;
}(Component);

AutoComplete.displayName = 'NeatUI.AutoComplete';
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
};
AutoComplete.defaultProps = {
    selectOnly: false,
    matchWidth: true,
    prefixCls: 'ne-auto-complete',
    suggestions: [],
    filter: defaultFilter,
    maximumDisplayingSuggestions: 5,
    waitTime: 200,
    matchHighlight: true
};
export default AutoComplete;