import _toConsumableArray from 'babel-runtime/helpers/toConsumableArray';
import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
import _defineProperty from 'babel-runtime/helpers/defineProperty';
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/cascader/Cascader.jsx';
/**
 * cascader.jsx
 *
 * @Author: zhangce
 * @Date: 17/8/29 下午2:28
 */

import React, { Fragment, cloneElement } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { Icon, Input, Menu, MenuItem, ParallelMenu, DropdownMenu } from '../index';
import { arrayTreeFilter, treeToPath } from '../util/arrayTreeFilter';
import { isEqualArrays } from '../util/isEqual';

/**
 * Cascader
 * */

var Cascader = function (_React$PureComponent) {
    _inherits(Cascader, _React$PureComponent);

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

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

        _initialiseProps.call(_this);

        _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 (this.props.loadOptionData && 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 _state = this.state,
                defaultIsOpen = _state.defaultIsOpen,
                selectedValue = _state.selectedValue,
                value = _state.value;

            var defaultIsOpenChanged = prevState.defaultIsOpen !== defaultIsOpen;
            if (defaultIsOpen) {
                this.searchInput && this.searchInput.focus();
                if (defaultIsOpenChanged && !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 _props = this.props,
                prefixCls = _props.prefixCls,
                className = _props.className,
                placeholder = _props.placeholder,
                searchable = _props.searchable,
                anchorEl = _props.anchorEl,
                inputProps = _props.inputProps,
                style = _props.style,
                size = _props.size;
            var _state2 = this.state,
                defaultIsOpen = _state2.defaultIsOpen,
                selectOptionMap = _state2.selectOptionMap,
                inputValue = _state2.inputValue;

            var classString = classNames('' + prefixCls, className);

            return anchorEl ? cloneElement(anchorEl, {
                onClick: this.handleClick
            }) : React.createElement(
                'div',
                {
                    className: classNames(classString, _defineProperty({}, prefixCls + '-clear-show', selectOptionMap.length || inputValue.length)), __source: {
                        fileName: _jsxFileName,
                        lineNumber: 392
                    },
                    __self: this
                },
                React.createElement(Input, {
                    type: 'text',
                    className: prefixCls + '-input',
                    placeholder: placeholder,
                    inputRef: this.setInputRef,
                    value: inputValue,
                    mask: !searchable || searchable && !defaultIsOpen ? this.renderLabel() : undefined,
                    onClick: this.handleClick,
                    onChange: this.handleSearch,
                    readOnly: !searchable,
                    suffix: React.createElement(
                        Fragment,
                        {
                            __source: {
                                fileName: _jsxFileName,
                                lineNumber: 407
                            },
                            __self: this
                        },
                        React.createElement(Icon, { className: prefixCls + '-clear', type: 'cancel-o', onClick: this.clearValue, __source: {
                                fileName: _jsxFileName,
                                lineNumber: 408
                            },
                            __self: this
                        }),
                        React.createElement(Icon, {
                            className: classNames(prefixCls + '-arrow', _defineProperty({}, 'turn-up', defaultIsOpen)),
                            type: 'down-arrow',
                            __source: {
                                fileName: _jsxFileName,
                                lineNumber: 409
                            },
                            __self: this
                        })
                    ),
                    inputProps: inputProps,
                    style: style,
                    size: size,
                    __source: {
                        fileName: _jsxFileName,
                        lineNumber: 396
                    },
                    __self: this
                })
            );
        }
    }, {
        key: 'render',
        value: function render() {
            var _props2 = this.props,
                prefixCls = _props2.prefixCls,
                pickerClass = _props2.pickerClass,
                children = _props2.children,
                changeOnSelect = _props2.changeOnSelect,
                options = _props2.options,
                position = _props2.position,
                trigger = _props2.trigger,
                defaultValue = _props2.defaultValue,
                searchable = _props2.searchable,
                noResultHolder = _props2.noResultHolder,
                loadOptionData = _props2.loadOptionData,
                labelRender = _props2.labelRender,
                onChange = _props2.onChange,
                anchorEl = _props2.anchorEl,
                inputProps = _props2.inputProps,
                size = _props2.size,
                other = _objectWithoutProperties(_props2, ['prefixCls', 'pickerClass', 'children', 'changeOnSelect', 'options', 'position', 'trigger', 'defaultValue', 'searchable', 'noResultHolder', 'loadOptionData', 'labelRender', 'onChange', 'anchorEl', 'inputProps', 'size']);

            var _state3 = this.state,
                defaultIsOpen = _state3.defaultIsOpen,
                searchDefaultIsOpen = _state3.searchDefaultIsOpen,
                selectedValue = _state3.selectedValue;

            return React.createElement(
                DropdownMenu,
                {
                    noClose: true,
                    defaultIsOpen: defaultIsOpen,
                    anchorEl: this.renderInput(),
                    onSelect: searchDefaultIsOpen ? this.handleSearchResultSelect : this.onSelect,
                    onOpenChange: this.handleMenuVisibleChange,
                    className: pickerClass,
                    trigger: trigger,
                    position: position, __source: {
                        fileName: _jsxFileName,
                        lineNumber: 445
                    },
                    __self: this
                },
                searchDefaultIsOpen ? this.initSearchResult() : React.createElement(
                    ParallelMenu,
                    Object.assign({
                        className: prefixCls + '-menu',
                        defaultValue: selectedValue,
                        options: options,
                        onChange: this.onChange,
                        changeOnSelect: changeOnSelect
                    }, other, {
                        __source: {
                            fileName: _jsxFileName,
                            lineNumber: 457
                        },
                        __self: this
                    }),
                    children
                )
            );
        }
    }]);

    return Cascader;
}(React.PureComponent);

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', 'hover']),
    /**
     * options子元素key值
     * */
    childrenKeyName: PropTypes.string
};
Cascader.defaultProps = {
    prefixCls: 'ne-cascader-picker',
    placeholder: '',
    size: 'medium',
    changeOnSelect: false,
    searchable: false,
    defaultValue: [],
    noResultHolder: 'Not Found',
    trigger: 'click',
    position: 'bottomLeft',
    childrenKeyName: 'children'
};

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

    this.getDefaultOptions = function (props) {
        var defaultValue = props.defaultValue,
            childrenKeyName = props.childrenKeyName;

        return defaultValue.length ? arrayTreeFilter(_this2.options, function (o, level) {
            return o.value === defaultValue[level];
        }, null, { childrenKeyName: childrenKeyName }) : [];
    };

    this.updateOptions = function (props) {
        var searchable = props.searchable;

        if (props.options) {
            _this2.options = props.options;
        } else {
            _this2.options = _this2.getTreeMapOptions(props.children);
        }
        if (searchable) {
            _this2.pathOptions = treeToPath(_this2.options);
        }
    };

    this.getTreeMapOptions = function (children) {
        return React.Children.map(children, function (ele) {
            var props = ele.props;
            var option = void 0;
            if (ele.type.displayName === 'NeatUI.SubMenu') {
                option = {
                    value: props.value,
                    label: props.title,
                    disabled: props.disabled || false,
                    children: _this2.getTreeMapOptions(props.children)
                };
            } else if (ele.type.displayName === 'NeatUI.MenuItem') {
                option = {
                    value: props.value,
                    disabled: props.disabled || false,
                    label: props.children,
                    isLastNode: props.isLastNode !== false
                };
            }
            return option;
        });
    };

    this.onChange = function (value, isLast) {
        var _props3 = _this2.props,
            searchable = _props3.searchable,
            loadOptionData = _props3.loadOptionData,
            childrenKeyName = _props3.childrenKeyName;

        var selectOptionMap = _this2.getDefaultOptions({
            defaultValue: [].concat(_toConsumableArray(value))
        });
        _this2.handleValueChange(selectOptionMap, !isLast);

        if (!searchable && loadOptionData) {
            var lastOption = selectOptionMap[selectOptionMap.length - 1];
            if (lastOption.isLastNode === false && lastOption[childrenKeyName] === void 0) {
                loadOptionData(selectOptionMap.map(function (o) {
                    return o.value;
                }), selectOptionMap);
                _this2.setState({
                    defaultIsOpen: true
                });
            }
        }
    };

    this.onSelect = function (e, value, isLast, level, selectedValue) {
        var onSelect = _this2.props.onSelect;

        _this2.setState({
            selectedValue: selectedValue
        });
        if (isLast) {
            _this2.setState({
                defaultIsOpen: false
            });
        }
        onSelect && onSelect(e, value, isLast);
    };

    this.handleMenuVisibleChange = function (isOpen) {
        var onPopVisibleChange = _this2.props.onPopVisibleChange;

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

    this.clearValue = function (e) {
        e && e.stopPropagation && e.stopPropagation();
        var _props4 = _this2.props,
            onChange = _props4.onChange,
            searchable = _props4.searchable;
        var inputValue = _this2.state.inputValue;
        //清理搜索框值

        if (searchable && inputValue !== '') {
            _this2.setState({
                inputValue: '',
                searchDefaultIsOpen: false
            });
            return;
        }
        //清理组件选中值
        _this2.setState({
            value: [],
            selectOptionMap: []
        });
        //触发onChange
        onChange([], []);
    };

    this.handleMenuClose = function () {
        _this2.setState({
            inputValue: '',
            defaultIsOpen: false,
            searchDefaultIsOpen: false
        });
    };

    this.handleSearch = function (e) {
        var inputValue = e.target.value;
        _this2.setState({
            inputValue: inputValue,
            searchDefaultIsOpen: inputValue.length > 0
        }, function () {
            var result = [];
            _this2.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) {
                            _iterator.return();
                        }
                    } finally {
                        if (_didIteratorError) {
                            throw _iteratorError;
                        }
                    }
                }
            });
            _this2.setState({
                searchResult: result
            });
        });
    };

    this.handleSearchResultSelect = function (e, value) {
        var searchResult = _this2.state.searchResult;

        var result = searchResult[value];
        _this2.handleValueChange(result, false);
    };

    this.handleValueChange = function (optionMap, isOpen) {
        var onChange = _this2.props.onChange;

        var newValue = optionMap.map(function (o) {
            return o.value;
        });
        _this2.setState(function (prevState, props) {
            if (!isEqualArrays(prevState.value, newValue)) {
                onChange && onChange(newValue, optionMap);
                return {
                    value: newValue,
                    selectOptionMap: [].concat(_toConsumableArray(optionMap))
                };
            }
        });
        _this2.setState({
            defaultIsOpen: isOpen
        });
    };

    this.initSearchResult = function () {
        var _props5 = _this2.props,
            noResultHolder = _props5.noResultHolder,
            prefixCls = _props5.prefixCls;
        var searchResult = _this2.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, __source: {
                        fileName: _jsxFileName,
                        lineNumber: 344
                    },
                    __self: _this2
                },
                label.join('/')
            );
        }) : React.createElement(
            MenuItem,
            { key: 'notFond', disabled: true, __source: {
                    fileName: _jsxFileName,
                    lineNumber: 350
                },
                __self: _this2
            },
            noResultHolder
        );
        return React.createElement(
            Menu,
            { selectable: true, className: prefixCls + '-search-menu', __source: {
                    fileName: _jsxFileName,
                    lineNumber: 355
                },
                __self: _this2
            },
            menuItems
        );
    };

    this.setInputRef = function (input) {
        _this2.searchInput = input;
    };

    this.handleClick = function () {
        var onClick = _this2.props.onClick;
        var defaultIsOpen = _this2.state.defaultIsOpen;


        onClick && onClick();
        if (_this2.options.length) {
            _this2.handleMenuVisibleChange(!defaultIsOpen);
        }
    };
};

export default Cascader;