"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Transfer = void 0;
var tslib_1 = require("tslib");
var react_1 = (0, tslib_1.__importDefault)(require("react"));
var lodash_1 = require("lodash");
var theme_1 = require("../theme");
var Selection_1 = require("./Selection");
var uncontrollable_1 = require("uncontrollable");
var ResultList_1 = (0, tslib_1.__importDefault)(require("./ResultList"));
var TableSelection_1 = (0, tslib_1.__importDefault)(require("./TableSelection"));
var helper_1 = require("../utils/helper");
var InputBox_1 = (0, tslib_1.__importDefault)(require("./InputBox"));
var Checkbox_1 = (0, tslib_1.__importDefault)(require("./Checkbox"));
var Tree_1 = (0, tslib_1.__importDefault)(require("./Tree"));
var icons_1 = require("./icons");
var AssociatedSelection_1 = (0, tslib_1.__importDefault)(require("./AssociatedSelection"));
var locale_1 = require("../locale");
var GroupedSelection_1 = (0, tslib_1.__importDefault)(require("./GroupedSelection"));
var ChainedSelection_1 = (0, tslib_1.__importDefault)(require("./ChainedSelection"));
var ResultTableList_1 = (0, tslib_1.__importDefault)(require("./ResultTableList"));
var ResultTreeList_1 = (0, tslib_1.__importDefault)(require("./ResultTreeList"));
var Transfer = /** @class */ (function (_super) {
    (0, tslib_1.__extends)(Transfer, _super);
    function Transfer() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.state = {
            inputValue: '',
            searchResult: null,
            isTreeDeferLoad: false,
            resultSelectMode: 'list'
        };
        _this.unmounted = false;
        _this.lazySearch = (0, lodash_1.debounce)(function () { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () {
            var inputValue, onSearch, result;
            var _this = this;
            return (0, tslib_1.__generator)(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        inputValue = this.state.inputValue;
                        if (!inputValue) {
                            return [2 /*return*/];
                        }
                        onSearch = this.props.onSearch;
                        return [4 /*yield*/, onSearch(inputValue, function (cancelExecutor) { return (_this.cancelSearch = cancelExecutor); })];
                    case 1:
                        result = _a.sent();
                        if (this.unmounted) {
                            return [2 /*return*/];
                        }
                        if (!Array.isArray(result)) {
                            throw new Error('onSearch 需要返回数组');
                        }
                        this.setState({
                            searchResult: result
                        });
                        return [2 /*return*/];
                }
            });
        }); }, 250, { trailing: true, leading: false });
        return _this;
    }
    Transfer.prototype.componentDidMount = function () {
        var _a, _b;
        (_b = (_a = this.props) === null || _a === void 0 ? void 0 : _a.onRef) === null || _b === void 0 ? void 0 : _b.call(_a, this);
    };
    Transfer.getDerivedStateFromProps = function (props) {
        // 计算是否是懒加载模式
        var isTreeDeferLoad = false;
        props.selectMode === 'tree' &&
            props.options.forEach(function (item) {
                if (item.defer) {
                    isTreeDeferLoad = true;
                }
            });
        // 计算结果的selectMode
        var resultSelectMode = 'list';
        if (props.selectMode === 'tree' &&
            props.resultListModeFollowSelect &&
            !isTreeDeferLoad) {
            resultSelectMode = 'tree';
        }
        if (props.selectMode === 'table' && props.resultListModeFollowSelect) {
            resultSelectMode = 'table';
        }
        return {
            isTreeDeferLoad: isTreeDeferLoad,
            resultSelectMode: resultSelectMode
        };
    };
    Transfer.prototype.componentWillUnmount = function () {
        this.lazySearch.cancel();
        this.unmounted = true;
    };
    Transfer.prototype.domRef = function (ref) {
        this.treeRef = ref;
    };
    Transfer.prototype.toggleAll = function () {
        var _a = this.props, options = _a.options, option2value = _a.option2value, onChange = _a.onChange, value = _a.value, onSelectAll = _a.onSelectAll;
        var valueArray = Selection_1.BaseSelection.value2array(value, options, option2value);
        var availableOptions = (0, helper_1.flattenTree)(options).filter(function (option, index, list) {
            return !option.disabled &&
                option.value !== void 0 &&
                list.indexOf(option) === index;
        });
        if (valueArray.length < availableOptions.length) {
            valueArray = availableOptions;
        }
        else {
            valueArray = [];
        }
        var newValue = option2value
            ? valueArray.map(function (item) { return option2value(item); })
            : valueArray;
        // > 0 全选。TODO：由于未来可能有逻辑：禁用清空不了，这里判断全选，得完善下
        newValue.length > 0 && (onSelectAll === null || onSelectAll === void 0 ? void 0 : onSelectAll(newValue));
        onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
    };
    // 全选，给予动作全选使用
    Transfer.prototype.selectAll = function () {
        var _a = this.props, options = _a.options, option2value = _a.option2value, onChange = _a.onChange;
        var availableOptions = (0, helper_1.flattenTree)(options).filter(function (option, index, list) {
            return !option.disabled &&
                option.value !== void 0 &&
                list.indexOf(option) === index;
        });
        var newValue = option2value
            ? availableOptions.map(function (item) { return option2value(item); })
            : availableOptions;
        onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
    };
    Transfer.prototype.clearAll = function () {
        var onChange = this.props.onChange;
        onChange && onChange([]);
    };
    Transfer.prototype.handleSearchKeyDown = function (e) {
        if (e.key === 'Enter') {
            e.preventDefault();
        }
    };
    Transfer.prototype.handleSearch = function (inputValue) {
        var _this = this;
        // text 有值的时候，走搜索否则直接走 handleSeachCancel ，等同于右侧的 clear 按钮
        this.setState({ inputValue: inputValue }, function () {
            if (inputValue) {
                // 如果有取消搜索，先取消掉。
                _this.cancelSearch && _this.cancelSearch();
                _this.lazySearch();
            }
            else {
                _this.handleSeachCancel();
            }
        });
    };
    Transfer.prototype.handleSeachCancel = function () {
        this.setState({
            inputValue: '',
            searchResult: null
        });
    };
    Transfer.prototype.getFlattenArr = function (options) {
        return (0, helper_1.flattenTree)(options).filter(function (option, index, list) {
            return !option.disabled &&
                option.value !== void 0 &&
                list.indexOf(option) === index;
        });
    };
    // 树搜索处理
    Transfer.prototype.handleSearchTreeChange = function (values, searchOptions) {
        var _a = this.props, onChange = _a.onChange, value = _a.value;
        var searchAvailableOptions = this.getFlattenArr(searchOptions);
        var useArr = (0, lodash_1.intersectionWith)(searchAvailableOptions, values, function (a, b) { return a.value === b.value; });
        var unuseArr = (0, lodash_1.differenceWith)(searchAvailableOptions, values, function (a, b) { return a.value === b.value; });
        var newArr = [];
        Array.isArray(value) &&
            value.forEach(function (item) {
                if (!unuseArr.find(function (v) { return v.value === item.value; })) {
                    newArr.push(item);
                }
            });
        useArr.forEach(function (item) {
            if (!newArr.find(function (v) { return v.value === item.value; })) {
                newArr.push(item);
            }
        });
        onChange && onChange(newArr);
    };
    Transfer.prototype.renderSelect = function (props) {
        var _this = this;
        var selectRender = props.selectRender, selectMode = props.selectMode, cx = props.classnames, selectTitle = props.selectTitle, onSearch = props.onSearch, disabled = props.disabled, options = props.options, statistics = props.statistics, __ = props.translate, _a = props.searchPlaceholder, searchPlaceholder = _a === void 0 ? __('Transfer.searchKeyword') : _a;
        if (selectRender) {
            return selectRender((0, tslib_1.__assign)((0, tslib_1.__assign)({}, props), { onSearch: this.handleSearch, onSearchCancel: this.handleSeachCancel, searchResult: this.state.searchResult }));
        }
        var checkedPartial = false;
        var checkedAll = false;
        checkedAll = this.availableOptions.every(function (option) { return _this.valueArray.indexOf(option) > -1; });
        checkedPartial = this.availableOptions.some(function (option) { return _this.valueArray.indexOf(option) > -1; });
        return (react_1.default.createElement(react_1.default.Fragment, null,
            react_1.default.createElement("div", { className: cx('Transfer-title', selectMode === 'table' ? 'Transfer-title--light' : '') },
                react_1.default.createElement("span", null,
                    (0, lodash_1.includes)(['list', 'tree'], selectMode) ? (react_1.default.createElement(Checkbox_1.default, { checked: checkedPartial, partial: checkedPartial && !checkedAll, onChange: props.onToggleAll || this.toggleAll, size: "sm" })) : null,
                    __(selectTitle || 'Transfer.available'),
                    statistics !== false ? (react_1.default.createElement("span", null,
                        "\uFF08",
                        this.availableOptions.length - this.valueArray.length,
                        "/",
                        this.availableOptions.length,
                        "\uFF09")) : null),
                (0, lodash_1.includes)(['chained', 'associated'], selectMode) ? (react_1.default.createElement("a", { onClick: props.onToggleAll || this.toggleAll, className: cx('Transfer-checkAll', disabled || !options.length ? 'is-disabled' : '') }, __('Select.checkAll'))) : null),
            onSearch ? (react_1.default.createElement("div", { className: cx('Transfer-search') },
                react_1.default.createElement(InputBox_1.default, { value: this.state.inputValue, onChange: this.handleSearch, clearable: false, onKeyDown: this.handleSearchKeyDown, placeholder: searchPlaceholder }, this.state.searchResult !== null ? (react_1.default.createElement("a", { onClick: this.handleSeachCancel },
                    react_1.default.createElement(icons_1.Icon, { icon: "close", className: "icon" }))) : (react_1.default.createElement(icons_1.Icon, { icon: "search", className: "icon" }))))) : null,
            this.state.searchResult !== null
                ? this.renderSearchResult(props)
                : this.renderOptions(props)));
    };
    Transfer.prototype.renderSearchResult = function (props) {
        var _this = this;
        var searchResultMode = props.searchResultMode, selectMode = props.selectMode, noResultsText = props.noResultsText, searchResultColumns = props.searchResultColumns, columns = props.columns, cx = props.classnames, value = props.value, disabled = props.disabled, onChange = props.onChange, option2value = props.option2value, optionItemRender = props.optionItemRender, cellRender = props.cellRender, multiple = props.multiple;
        var _a = this.state, isTreeDeferLoad = _a.isTreeDeferLoad, searchResult = _a.searchResult;
        var options = searchResult !== null && searchResult !== void 0 ? searchResult : [];
        var mode = searchResultMode || selectMode;
        var resultColumns = searchResultColumns || columns;
        return mode === 'table' ? (react_1.default.createElement(TableSelection_1.default, { placeholder: noResultsText, className: cx('Transfer-selection'), columns: resultColumns, options: options, value: value, disabled: disabled, onChange: onChange, option2value: option2value, cellRender: cellRender, itemRender: optionItemRender, multiple: multiple })) : mode === 'tree' ? (react_1.default.createElement(Tree_1.default, { onRef: this.domRef, placeholder: noResultsText, className: cx('Transfer-selection'), options: options, value: value, disabled: disabled, onChange: function (value) {
                return _this.handleSearchTreeChange(value, options);
            }, joinValues: false, showIcon: false, multiple: true, cascade: true, onlyChildren: !isTreeDeferLoad, itemRender: optionItemRender })) : mode === 'chained' ? (react_1.default.createElement(ChainedSelection_1.default, { placeholder: noResultsText, className: cx('Transfer-selection'), options: options, value: value, disabled: disabled, onChange: onChange, option2value: option2value, itemRender: optionItemRender, multiple: multiple })) : (react_1.default.createElement(GroupedSelection_1.default, { placeholder: noResultsText, className: cx('Transfer-selection'), options: options, value: value, disabled: disabled, onChange: onChange, option2value: option2value, itemRender: optionItemRender, multiple: multiple }));
    };
    Transfer.prototype.renderOptions = function (props) {
        var selectMode = props.selectMode, columns = props.columns, options = props.options, value = props.value, disabled = props.disabled, onChange = props.onChange, option2value = props.option2value, cx = props.classnames, onDeferLoad = props.onDeferLoad, leftOptions = props.leftOptions, leftMode = props.leftMode, rightMode = props.rightMode, cellRender = props.cellRender, leftDefaultValue = props.leftDefaultValue, optionItemRender = props.optionItemRender, multiple = props.multiple, noResultsText = props.noResultsText;
        return selectMode === 'table' ? (react_1.default.createElement(TableSelection_1.default, { className: cx('Transfer-selection'), columns: columns, options: options || [], value: value, disabled: disabled, onChange: onChange, option2value: option2value, onDeferLoad: onDeferLoad, cellRender: cellRender, multiple: multiple })) : selectMode === 'tree' ? (react_1.default.createElement(Tree_1.default, { onRef: this.domRef, placeholder: noResultsText, className: cx('Transfer-selection'), options: options, value: value, onChange: onChange, onlyChildren: !this.state.isTreeDeferLoad, itemRender: optionItemRender, onDeferLoad: onDeferLoad, joinValues: false, showIcon: false, multiple: true, cascade: true })) : selectMode === 'chained' ? (react_1.default.createElement(ChainedSelection_1.default, { className: cx('Transfer-selection'), options: options || [], value: value, disabled: disabled, onChange: onChange, option2value: option2value, onDeferLoad: onDeferLoad, itemRender: optionItemRender, multiple: multiple })) : selectMode === 'associated' ? (react_1.default.createElement(AssociatedSelection_1.default, { className: cx('Transfer-selection'), options: options || [], value: value, disabled: disabled, onChange: onChange, option2value: option2value, onDeferLoad: onDeferLoad, columns: columns, leftOptions: leftOptions || [], leftMode: leftMode, rightMode: rightMode, leftDefaultValue: leftDefaultValue, itemRender: optionItemRender, multiple: multiple })) : (react_1.default.createElement(GroupedSelection_1.default, { className: cx('Transfer-selection'), options: options || [], value: value, disabled: disabled, onChange: onChange, option2value: option2value, onDeferLoad: onDeferLoad, itemRender: optionItemRender, multiple: multiple }));
    };
    Transfer.prototype.renderResult = function () {
        var _a = this.props, columns = _a.columns, options = _a.options, disabled = _a.disabled, option2value = _a.option2value, cx = _a.classnames, cellRender = _a.cellRender, onChange = _a.onChange, value = _a.value, resultItemRender = _a.resultItemRender, resultSearchable = _a.resultSearchable, resultSearchPlaceholder = _a.resultSearchPlaceholder, onResultSearch = _a.onResultSearch, sortable = _a.sortable, __ = _a.translate;
        var _b = this.state, resultSelectMode = _b.resultSelectMode, isTreeDeferLoad = _b.isTreeDeferLoad;
        var searchable = !isTreeDeferLoad && resultSearchable;
        var placeholder = resultSearchPlaceholder || __('Transfer.selectFromLeft');
        return resultSelectMode === 'table' ? (react_1.default.createElement(ResultTableList_1.default, { classnames: cx, columns: columns, options: options || [], value: value, disabled: disabled, option2value: option2value, cellRender: cellRender, onChange: onChange, multiple: false, searchable: searchable, placeholder: placeholder, onSearch: onResultSearch })) : resultSelectMode === 'tree' ? (react_1.default.createElement(ResultTreeList_1.default, { classnames: cx, options: options, valueField: 'value', value: value || [], onChange: onChange, itemRender: resultItemRender, searchable: searchable, placeholder: placeholder, onSearch: onResultSearch })) : (react_1.default.createElement(ResultList_1.default, { className: cx('Transfer-value'), sortable: sortable, disabled: disabled, value: value, onChange: onChange, placeholder: placeholder, itemRender: resultItemRender, columns: columns, options: options || [], option2value: option2value, cellRender: cellRender, searchable: searchable, onSearch: onResultSearch }));
    };
    Transfer.prototype.render = function () {
        var _a = this.props, inline = _a.inline, cx = _a.classnames, className = _a.className, value = _a.value, resultTitle = _a.resultTitle, options = _a.options, option2value = _a.option2value, disabled = _a.disabled, statistics = _a.statistics, showArrow = _a.showArrow, resultListModeFollowSelect = _a.resultListModeFollowSelect, _b = _a.selectMode, selectMode = _b === void 0 ? 'list' : _b, __ = _a.translate;
        this.valueArray = Selection_1.BaseSelection.value2array(value, options, option2value);
        this.availableOptions = (0, helper_1.flattenTree)(options).filter(function (option, index, list) {
            return !option.disabled &&
                option.value !== void 0 &&
                list.indexOf(option) === index;
        });
        var tableType = resultListModeFollowSelect && selectMode === 'table';
        return (react_1.default.createElement("div", { className: cx('Transfer', className, inline ? 'Transfer--inline' : '') },
            react_1.default.createElement("div", { className: cx('Transfer-select') }, this.renderSelect(this.props)),
            react_1.default.createElement("div", { className: cx('Transfer-mid') }, showArrow /*todo 需要改成确认模式，即：点了按钮才到右边 */ ? (react_1.default.createElement("div", { className: cx('Transfer-arrow') },
                react_1.default.createElement(icons_1.Icon, { icon: "right-arrow", className: "icon" }))) : null),
            react_1.default.createElement("div", { className: cx('Transfer-result') },
                react_1.default.createElement("div", { className: cx('Transfer-title', tableType ? 'Transfer-table-title' : '', selectMode === 'table' ? 'Transfer-title--light' : '') },
                    react_1.default.createElement("span", null,
                        __(resultTitle || 'Transfer.selectd'),
                        statistics !== false ? (react_1.default.createElement("span", null,
                            "\uFF08",
                            this.valueArray.length,
                            "\uFF09")) : null),
                    react_1.default.createElement("a", { onClick: this.clearAll, className: cx('Transfer-clearAll', disabled || !this.valueArray.length ? 'is-disabled' : '') }, __('clear'))),
                this.renderResult())));
    };
    var _a, _b, _c;
    Transfer.defaultProps = {
        multiple: true,
        resultListModeFollowSelect: false,
        selectMode: 'list'
    };
    (0, tslib_1.__decorate)([
        helper_1.autobind,
        (0, tslib_1.__metadata)("design:type", Function),
        (0, tslib_1.__metadata)("design:paramtypes", [Object]),
        (0, tslib_1.__metadata)("design:returntype", void 0)
    ], Transfer.prototype, "domRef", null);
    (0, tslib_1.__decorate)([
        helper_1.autobind,
        (0, tslib_1.__metadata)("design:type", Function),
        (0, tslib_1.__metadata)("design:paramtypes", []),
        (0, tslib_1.__metadata)("design:returntype", void 0)
    ], Transfer.prototype, "toggleAll", null);
    (0, tslib_1.__decorate)([
        helper_1.autobind,
        (0, tslib_1.__metadata)("design:type", Function),
        (0, tslib_1.__metadata)("design:paramtypes", []),
        (0, tslib_1.__metadata)("design:returntype", void 0)
    ], Transfer.prototype, "clearAll", null);
    (0, tslib_1.__decorate)([
        helper_1.autobind,
        (0, tslib_1.__metadata)("design:type", Function),
        (0, tslib_1.__metadata)("design:paramtypes", [typeof (_a = typeof react_1.default !== "undefined" && react_1.default.KeyboardEvent) === "function" ? _a : Object]),
        (0, tslib_1.__metadata)("design:returntype", void 0)
    ], Transfer.prototype, "handleSearchKeyDown", null);
    (0, tslib_1.__decorate)([
        helper_1.autobind,
        (0, tslib_1.__metadata)("design:type", Function),
        (0, tslib_1.__metadata)("design:paramtypes", [String]),
        (0, tslib_1.__metadata)("design:returntype", void 0)
    ], Transfer.prototype, "handleSearch", null);
    (0, tslib_1.__decorate)([
        helper_1.autobind,
        (0, tslib_1.__metadata)("design:type", Function),
        (0, tslib_1.__metadata)("design:paramtypes", []),
        (0, tslib_1.__metadata)("design:returntype", void 0)
    ], Transfer.prototype, "handleSeachCancel", null);
    (0, tslib_1.__decorate)([
        helper_1.autobind,
        (0, tslib_1.__metadata)("design:type", Function),
        (0, tslib_1.__metadata)("design:paramtypes", [typeof (_b = typeof Array !== "undefined" && Array) === "function" ? _b : Object, typeof (_c = typeof Array !== "undefined" && Array) === "function" ? _c : Object]),
        (0, tslib_1.__metadata)("design:returntype", void 0)
    ], Transfer.prototype, "handleSearchTreeChange", null);
    return Transfer;
}(react_1.default.Component));
exports.Transfer = Transfer;
exports.default = (0, theme_1.themeable)((0, locale_1.localeable)((0, uncontrollable_1.uncontrollable)(/** @class */ (function (_super) {
    (0, tslib_1.__extends)(class_1, _super);
    function class_1() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    return class_1;
}(Transfer)), {
    value: 'onChange'
})));
//# sourceMappingURL=./components/Transfer.js.map
