import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
import _defineProperty from 'babel-runtime/helpers/defineProperty';
import _toConsumableArray from 'babel-runtime/helpers/toConsumableArray';
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';

/**
 * 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.state = {
            defaultIsOpen: false,
            searchDefaultIsOpen: false,
            value: props.defaultValue,
            labelMap: _this.getDefaultLabelMap(props),
            selectOptionMap: _this.getDefaultOptions(props),
            inputValue: '',
            pathOptions: [],
            searchResult: [],
            hideCursor: true
        };
        return _this;
    }

    _createClass(Cascader, [{
        key: 'componentDidMount',
        value: function componentDidMount() {
            var searchable = this.props.searchable;

            if (searchable) {
                this.setState({
                    pathOptions: treeToPath(this.options)
                });
            }
        }
    }, {
        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,
                    labelMap: this.getDefaultLabelMap(newProps),
                    selectOptionMap: this.getDefaultOptions(newProps)
                });
            }
        }
    }, {
        key: 'componentDidUpdate',
        value: function componentDidUpdate(prevProps, prevState) {
            var _state = this.state,
                defaultIsOpen = _state.defaultIsOpen,
                searchDefaultIsOpen = _state.searchDefaultIsOpen,
                value = _state.value,
                selectOptionMap = _state.selectOptionMap;

            var searchDefaultIsOpenChanged = prevState.searchDefaultIsOpen !== searchDefaultIsOpen;
            var defaultIsOpenChanged = prevState.defaultIsOpen !== defaultIsOpen;
            if (defaultIsOpen && this.searchInput) {
                this.searchInput.focus();
            }
            if (searchDefaultIsOpenChanged) {
                if (!searchDefaultIsOpen) {
                    this.setState({
                        inputValue: ''
                    });
                }
            }

            if (defaultIsOpenChanged) {
                if (defaultIsOpen && selectOptionMap.map(function (o) {
                    return o.value;
                }).toString() !== value.toString()) {
                    this.setState({
                        value: [].concat(_toConsumableArray(value)),
                        selectOptionMap: this.getDefaultOptions({
                            defaultValue: value
                        })
                    });
                }
            }
        }
    }, {
        key: 'renderInput',
        value: function renderInput() {
            var _classNames;

            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,
                selectOptionMap = _state2.selectOptionMap,
                defaultIsOpen = _state2.defaultIsOpen,
                searchDefaultIsOpen = _state2.searchDefaultIsOpen,
                labelMap = _state2.labelMap,
                value = _state2.value,
                inputValue = _state2.inputValue,
                hideCursor = _state2.hideCursor;

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

            return anchorEl ? cloneElement(anchorEl, {
                onClick: this.handleClick
            }) : React.createElement(
                'div',
                {
                    className: classNames(classString, (_classNames = {}, _defineProperty(_classNames, prefixCls + '-clear-show', labelMap.length || inputValue.length), _defineProperty(_classNames, prefixCls + '-hide-cursor', hideCursor), _classNames)),
                    onClick: this.handleClick, __source: {
                        fileName: _jsxFileName,
                        lineNumber: 413
                    },
                    __self: this
                },
                React.createElement(Input, {
                    type: 'text',
                    className: prefixCls + '-input',
                    placeholder: placeholder,
                    value: inputValue,
                    mask: !searchable || searchable && !defaultIsOpen ? this.renderLabel() : undefined,
                    onClick: this.handleClick,
                    onChange: this.handleSearch,
                    inputRef: this.setInputRef,
                    readOnly: !searchable,
                    suffix: React.createElement(
                        Fragment,
                        {
                            __source: {
                                fileName: _jsxFileName,
                                lineNumber: 430
                            },
                            __self: this
                        },
                        React.createElement(Icon, { className: prefixCls + '-clear', type: 'cancel-o', onClick: this.clearValue, __source: {
                                fileName: _jsxFileName,
                                lineNumber: 431
                            },
                            __self: this
                        }),
                        React.createElement(Icon, {
                            className: classNames(prefixCls + '-arrow', _defineProperty({}, 'turn-up', defaultIsOpen)),
                            type: 'down-arrow',
                            __source: {
                                fileName: _jsxFileName,
                                lineNumber: 432
                            },
                            __self: this
                        })
                    ),
                    inputProps: inputProps,
                    style: style,
                    size: size === 'base' ? 'medium' : size,
                    __source: {
                        fileName: _jsxFileName,
                        lineNumber: 419
                    },
                    __self: this
                })
            );
        }
    }, {
        key: 'renderLabel',
        value: function renderLabel() {
            var labelRender = this.props.labelRender;
            var labelMap = this.state.labelMap;

            return labelRender ? labelRender(labelMap) : labelMap.join('/');
        }
    }, {
        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,
                value = _state3.value;

            var classString = classNames(prefixCls + '-picker', pickerClass);
            return React.createElement(
                DropdownMenu,
                {
                    noClose: true,
                    defaultIsOpen: defaultIsOpen,
                    anchorEl: this.renderInput(),
                    onSelect: this.onSelect,
                    onOpenChange: this.handleMenuVisibleChange,
                    className: classString,
                    trigger: trigger,
                    position: position, __source: {
                        fileName: _jsxFileName,
                        lineNumber: 475
                    },
                    __self: this
                },
                React.createElement(
                    ParallelMenu,
                    Object.assign({
                        className: prefixCls + '-menu',
                        defaultValue: value,
                        options: options,
                        changeOnSelect: changeOnSelect,
                        defaultMenu: searchDefaultIsOpen ? this.initSearchResult() : null
                    }, other, {
                        __source: {
                            fileName: _jsxFileName,
                            lineNumber: 484
                        },
                        __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
};
Cascader.defaultProps = {
    prefixCls: 'ne-cascader-picker',
    placeholder: '',
    size: 'medium',
    changeOnSelect: false,
    searchable: false,
    defaultValue: [],
    noResultHolder: 'Not Found',
    trigger: 'click',
    position: 'bottomLeft'
};

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

    this.updateOptions = function (props) {
        if (props.options) {
            _this2.options = props.options;
        } else {
            _this2.options = _this2.getTreeMapOptions(props.children);
        }
    };

    this.getTreeMapOptions = function (chidren) {
        return React.Children.map(chidren, 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.handleClick = function () {
        var _props3 = _this2.props,
            onClick = _props3.onClick,
            searchable = _props3.searchable;
        var defaultIsOpen = _this2.state.defaultIsOpen;


        if (searchable) {
            _this2.setState({
                hideCursor: false
            });
        }

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

    this.onSelect = function (e, value, isLast, level) {
        var _props4 = _this2.props,
            onSelect = _props4.onSelect,
            changeOnSelect = _props4.changeOnSelect,
            searchable = _props4.searchable,
            loadOptionData = _props4.loadOptionData;
        var selectOptionMap = _this2.state.selectOptionMap;

        var newValue = selectOptionMap.map(function (o) {
            return o.value;
        });
        newValue[level] = value;
        newValue = newValue.slice(0, level + 1);
        selectOptionMap = _this2.getDefaultOptions({
            defaultValue: newValue
        });
        var lastOption = selectOptionMap[selectOptionMap.length - 1];
        _this2.setState({
            selectOptionMap: selectOptionMap,
            hideCursor: true
        });

        if (changeOnSelect || isLast) {
            _this2.handleValueChange(selectOptionMap, !isLast);
        }
        if (!searchable && lastOption.isLastNode === false && lastOption.children === void 0 && loadOptionData) {
            loadOptionData(selectOptionMap.map(function (o) {
                return o.value;
            }), selectOptionMap);
            _this2.setState({
                defaultIsOpen: true
            });
        }
        onSelect && onSelect(e, value, isLast);
    };

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

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

    this.clearValue = function (e) {
        e && e.stopPropagation && e.stopPropagation();
        var onChange = _this2.props.onChange;
        var inputValue = _this2.state.inputValue;

        if (inputValue !== '') {
            _this2.setState({
                inputValue: '',
                searchDefaultIsOpen: false
            });
            return;
        }
        _this2.setState({
            value: [],
            labelMap: [],
            selectOptionMap: []
        });
        onChange([], []);
    };

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

    this.handleSearch = function (e) {
        var pathOptions = _this2.state.pathOptions;

        var inputValue = e.target.value;
        _this2.setState({
            inputValue: inputValue,
            searchDefaultIsOpen: inputValue.length > 0
        }, function () {
            var result = [];
            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 (prevState.value.toString() !== newValue.toString()) {
                onChange && onChange(newValue, optionMap);
                return {
                    value: newValue,
                    labelMap: optionMap.map(function (o) {
                        return o.label;
                    })
                };
            }
        });
        _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;
                }
            });

            var menuItemEle = React.createElement(
                MenuItem,
                { value: index, disabled: disabled, key: index, __source: {
                        fileName: _jsxFileName,
                        lineNumber: 361
                    },
                    __self: _this2
                },
                label.join('/')
            );
            return menuItemEle;
        }) : React.createElement(
            MenuItem,
            { key: 'notFond', disabled: true, __source: {
                    fileName: _jsxFileName,
                    lineNumber: 368
                },
                __self: _this2
            },
            noResultHolder
        );
        return React.createElement(
            Menu,
            { onSelect: _this2.handleSearchResultSelect, selectable: true, className: prefixCls + '-search-menu', __source: {
                    fileName: _jsxFileName,
                    lineNumber: 373
                },
                __self: _this2
            },
            menuItems
        );
    };

    this.getDefaultLabelMap = function (props) {
        var defaultValue = props.defaultValue;

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

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

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

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

export default Cascader;