"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var api_1 = require("../../utils/api");
var helper_1 = require("../../utils/helper");
var mobx_1 = require("mobx");
var Item_1 = require("./Item");
var react_1 = tslib_1.__importDefault(require("react"));
var tpl_builtin_1 = require("../../utils/tpl-builtin");
var Select_1 = require("../../components/Select");
exports.Option = Select_1.Option;
function registerOptionsControl(config) {
    var Control = config.component;
    // @observer
    var FormOptionsItem = /** @class */ (function (_super) {
        tslib_1.__extends(FormOptionsItem, _super);
        function FormOptionsItem(props) {
            var _this = _super.call(this, props) || this;
            var formItem = props.formItem;
            formItem && props.options && formItem.setOptions(Select_1.normalizeOptions(props.options));
            _this.handleToggle = _this.handleToggle.bind(_this);
            _this.handleToggleAll = _this.handleToggleAll.bind(_this);
            _this.setOptions = _this.setOptions.bind(_this);
            _this.syncOptions = _this.syncOptions.bind(_this);
            _this.setLoading = _this.setLoading.bind(_this);
            _this.inputRef = _this.inputRef.bind(_this);
            _this.reload = _this.reload.bind(_this);
            return _this;
        }
        FormOptionsItem.prototype.componentWillMount = function () {
            var _this = this;
            var _a = this.props, initFetch = _a.initFetch, formItem = _a.formItem, source = _a.source, data = _a.data, setPrinstineValue = _a.setPrinstineValue, defaultValue = _a.defaultValue, multiple = _a.multiple, joinValues = _a.joinValues, extractValue = _a.extractValue, addHook = _a.addHook, formInited = _a.formInited, valueField = _a.valueField;
            if (formItem) {
                this.reaction = mobx_1.reaction(function () { return JSON.stringify([formItem.loading, formItem.selectedOptions, formItem.filteredOptions]); }, function () { return _this.forceUpdate(); });
            }
            var loadOptions = initFetch !== false;
            if (/^\$(?:([a-z0-9_.]+)|{.+})$/.test(source) && formItem) {
                formItem.setOptions(Select_1.normalizeOptions(tpl_builtin_1.resolveVariableAndFilter(source, data, '| raw') || []));
                loadOptions = false;
            }
            if (formItem && joinValues === false && defaultValue) {
                var selectedOptions = extractValue
                    ? formItem.selectedOptions.map(function (selectedOption) { return selectedOption[valueField || 'value']; })
                    : formItem.selectedOptions;
                setPrinstineValue(multiple ? selectedOptions.concat() : formItem.selectedOptions[0]);
            }
            loadOptions && (formInited ? this.reload() : addHook && addHook(this.reload, 'init'));
        };
        FormOptionsItem.prototype.componentDidMount = function () {
            this.normalizeValue();
        };
        FormOptionsItem.prototype.shouldComponentUpdate = function (nextProps) {
            if (config.strictMode === false || nextProps.strictMode === false) {
                return true;
            }
            if (helper_1.anyChanged([
                'formPristine',
                'addOn',
                'disabled',
                'placeholder',
                'required',
                'formMode',
                'className',
                'inputClassName',
                'labelClassName',
                'label',
                'inline',
                'options',
                'size',
                'btnClassName',
                'btnActiveClassName',
                'buttons',
                'columnsCount',
                'multiple',
                'hideRoot',
                'checkAll',
                'showIcon',
                'showRadio',
                'btnDisabled'
            ], this.props, nextProps)) {
                return true;
            }
            return false;
        };
        FormOptionsItem.prototype.componentWillReceiveProps = function (nextProps) {
            var props = this.props;
            var formItem = nextProps.formItem;
            if (!formItem) {
                return;
            }
            else if (!props.formItem) {
                // todo 优化 name 变化情况。
            }
            if (props.value !== nextProps.value || formItem.expressionsInOptions) {
                formItem.syncOptions();
            }
            if (props.options !== nextProps.options && formItem) {
                formItem.setOptions(Select_1.normalizeOptions(nextProps.options || []));
            }
            else if (config.autoLoadOptionsFromSource !== false &&
                nextProps.source &&
                formItem &&
                (props.source !== nextProps.source || props.data !== nextProps.data)) {
                if (/^\$(?:([a-z0-9_.]+)|{.+})$/.test(nextProps.source)) {
                    var options = tpl_builtin_1.resolveVariableAndFilter(props.source, props.data, '| raw');
                    var nextOptions = tpl_builtin_1.resolveVariableAndFilter(nextProps.source, nextProps.data, '| raw');
                    options !== nextOptions && formItem.setOptions(Select_1.normalizeOptions(nextOptions || []));
                }
                else if (api_1.isApiOutdated(props.source, nextProps.source, props.data, nextProps.data)) {
                    formItem.loadOptions(nextProps.source, nextProps.data, undefined, true, nextProps.onChange);
                }
            }
        };
        FormOptionsItem.prototype.componentDidUpdate = function () {
            this.normalizeValue();
        };
        FormOptionsItem.prototype.componentWillUnmount = function () {
            this.props.removeHook && this.props.removeHook(this.reload, 'init');
            this.reaction && this.reaction();
        };
        FormOptionsItem.prototype.normalizeValue = function () {
            var _a = this.props, joinValues = _a.joinValues, extractValue = _a.extractValue, value = _a.value, multiple = _a.multiple, formItem = _a.formItem, valueField = _a.valueField;
            if (!formItem || joinValues !== false || !formItem.options.length) {
                return;
            }
            if (extractValue === false && (typeof value === 'string' || typeof value === 'number')) {
                formItem.changeValue(multiple ? formItem.selectedOptions.concat() : formItem.selectedOptions[0]);
            }
            else if (extractValue === true &&
                value &&
                !((Array.isArray(value) && value.every(function (val) { return typeof val === 'string' || typeof val === 'number'; })) ||
                    typeof value === 'string' ||
                    typeof value === 'number')) {
                var selectedOptions = formItem.selectedOptions.map(function (selectedOption) { return selectedOption[valueField || 'value']; });
                formItem.changeValue(multiple ? selectedOptions.concat() : selectedOptions[0]);
            }
        };
        FormOptionsItem.prototype.getWrappedInstance = function () {
            return this.input;
        };
        FormOptionsItem.prototype.inputRef = function (ref) {
            this.input = ref;
        };
        FormOptionsItem.prototype.handleToggle = function (option, submitOnChange) {
            var _a = this.props, onChange = _a.onChange, joinValues = _a.joinValues, extractValue = _a.extractValue, valueField = _a.valueField, delimiter = _a.delimiter, clearable = _a.clearable, resetValue = _a.resetValue, multiple = _a.multiple, formItem = _a.formItem;
            if (!formItem) {
                return;
            }
            var valueArray = formItem.selectedOptions.concat();
            var idx = valueArray.indexOf(option);
            var newValue = '';
            if (multiple) {
                if (~idx) {
                    valueArray.splice(idx, 1);
                }
                else {
                    valueArray.push(option);
                }
                newValue = valueArray;
                if (joinValues) {
                    newValue = newValue.map(function (item) { return item[valueField || 'value']; }).join(delimiter);
                }
                else if (extractValue) {
                    newValue = newValue.map(function (item) { return item[valueField || 'value']; });
                }
            }
            else {
                if (~idx && clearable) {
                    valueArray.splice(idx, 1);
                }
                else {
                    valueArray = [option];
                }
                newValue = valueArray[0] || resetValue;
                if (joinValues && newValue) {
                    newValue = newValue[valueField || 'value'];
                }
            }
            onChange && onChange(newValue, submitOnChange);
        };
        FormOptionsItem.prototype.handleToggleAll = function () {
            var _a = this.props, onChange = _a.onChange, joinValues = _a.joinValues, extractValue = _a.extractValue, valueField = _a.valueField, delimiter = _a.delimiter, resetValue = _a.resetValue, multiple = _a.multiple, formItem = _a.formItem;
            if (!formItem) {
                return;
            }
            var valueArray = formItem.selectedOptions.length === formItem.filteredOptions.length
                ? []
                : formItem.filteredOptions.concat();
            var newValue = '';
            if (multiple) {
                newValue = valueArray;
                if (joinValues) {
                    newValue = newValue.map(function (item) { return item[valueField || 'value']; }).join(delimiter);
                }
                else if (extractValue) {
                    newValue = newValue.map(function (item) { return item[valueField || 'value']; });
                }
            }
            else {
                newValue = valueArray[0] || resetValue;
                if (joinValues && newValue) {
                    newValue = newValue[valueField || 'value'];
                }
            }
            onChange && onChange(newValue);
        };
        // 当有 action 触发，如果指定了 reload 目标组件，有可能会来到这里面来
        FormOptionsItem.prototype.reload = function () {
            var _a = this.props, source = _a.source, formItem = _a.formItem, data = _a.data, onChange = _a.onChange;
            if (config.autoLoadOptionsFromSource === false || !formItem || !api_1.isEffectiveApi(source, data)) {
                return;
            }
            return formItem.loadOptions(source, data, undefined, false, onChange);
        };
        FormOptionsItem.prototype.focus = function () {
            this.input && this.input.focus && this.input.focus();
        };
        FormOptionsItem.prototype.setOptions = function (options) {
            var formItem = this.props.formItem;
            formItem && formItem.setOptions(Select_1.normalizeOptions(options || []));
        };
        FormOptionsItem.prototype.syncOptions = function () {
            var formItem = this.props.formItem;
            formItem && formItem.syncOptions();
        };
        FormOptionsItem.prototype.setLoading = function (value) {
            var formItem = this.props.formItem;
            formItem && formItem.setLoading(value);
        };
        FormOptionsItem.prototype.render = function () {
            var _a = this.props, value = _a.value, formItem = _a.formItem;
            return (react_1.default.createElement(Control, tslib_1.__assign({}, this.props, { ref: this.inputRef, options: formItem ? formItem.filteredOptions : [], onToggle: this.handleToggle, onToggleAll: this.handleToggleAll, selectedOptions: formItem ? formItem.getSelectedOptions(value) : [], loading: formItem ? formItem.loading : false, setLoading: this.setLoading, setOptions: this.setOptions, syncOptions: this.syncOptions, reloadOptions: this.reload })));
        };
        FormOptionsItem.displayName = "OptionsControl(" + config.type + ")";
        FormOptionsItem.defaultProps = tslib_1.__assign({ delimiter: ',', labelField: 'label', valueField: 'value', joinValues: true, extractValue: false, multiple: false, placeholder: '请选择', resetValue: '' }, Control.defaultProps);
        FormOptionsItem.propsList = Control.propsList ? tslib_1.__spreadArrays(Control.propsList) : [];
        FormOptionsItem.ComposedComponent = Control;
        return FormOptionsItem;
    }(react_1.default.Component));
    return Item_1.registerFormItem(tslib_1.__assign(tslib_1.__assign({}, config), { strictMode: false, component: FormOptionsItem }));
}
exports.registerOptionsControl = registerOptionsControl;
function OptionsControl(config) {
    return function (component) {
        var renderer = registerOptionsControl(tslib_1.__assign(tslib_1.__assign({}, config), { component: component }));
        return renderer.component;
    };
}
exports.OptionsControl = OptionsControl;
function highlight(text, input, hlClassName) {
    if (hlClassName === void 0) { hlClassName = 'is-matched'; }
    if (!input) {
        return text;
    }
    text = String(text);
    var reg = new RegExp(input.replace(/([\$\^\*\+\-\?\.\(\)\|\[\]\\])/, '\\$1'), 'i');
    if (!reg.test(text)) {
        return text;
    }
    var parts = text.split(reg);
    var dom = [];
    parts.forEach(function (text, index) {
        text && dom.push(react_1.default.createElement("span", { key: index }, text));
        dom.push(react_1.default.createElement("span", { className: hlClassName, key: index + "-hl" }, input));
    });
    dom.pop();
    return dom;
}
exports.highlight = highlight;
//# sourceMappingURL=./renderers/Form/Options.js.map
