"use strict";
/**
 * @file Tree
 * @description 树形组件
 * @author fex
 */
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var react_1 = tslib_1.__importDefault(require("react"));
var helper_1 = require("../utils/helper");
var Checkboxes_1 = require("./Checkboxes");
var theme_1 = require("../theme");
var Options_1 = require("../renderers/Form/Options");
var icons_1 = require("./icons");
var TreeSelector = /** @class */ (function (_super) {
    tslib_1.__extends(TreeSelector, _super);
    function TreeSelector() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    TreeSelector.prototype.componentWillMount = function () {
        var props = this.props;
        this.setState({
            value: Checkboxes_1.value2array(props.value, {
                joinValues: props.joinValues,
                extractValue: props.extractValue,
                multiple: props.multiple,
                delimiter: props.delimiter,
                valueField: props.valueField,
                options: props.data
            }),
            unfolded: this.syncUnFolded(props),
            editItem: null,
            addItem: null,
            addingItem: null,
            editingItem: null,
            addTop: false // 添加一级
        });
    };
    TreeSelector.prototype.componentWillReceiveProps = function (nextProps) {
        var toUpdate = {};
        if (this.props.value !== nextProps.value || this.props.data !== nextProps.data) {
            toUpdate.value = Checkboxes_1.value2array(nextProps.value, {
                joinValues: nextProps.joinValues,
                extractValue: nextProps.extractValue,
                multiple: nextProps.multiple,
                delimiter: nextProps.delimiter,
                valueField: nextProps.valueField,
                options: nextProps.data
            });
        }
        if (this.props.data !== nextProps.data) {
            toUpdate.unfolded = this.syncUnFolded(nextProps);
        }
        this.setState(toUpdate);
    };
    TreeSelector.prototype.syncUnFolded = function (props) {
        // 初始化树节点的展开状态
        var unfolded = {};
        var _a = this.props, foldedField = _a.foldedField, unfoldedField = _a.unfoldedField;
        helper_1.eachTree(props.data, function (node, index, level) {
            if (node.children && node.children.length) {
                var ret = true;
                if (unfoldedField && typeof node[unfoldedField] !== 'undefined') {
                    ret = !!node[unfoldedField];
                }
                else if (foldedField && typeof node[foldedField] !== 'undefined') {
                    ret = !node[foldedField];
                }
                else {
                    ret = !!props.initiallyOpen;
                    if (!ret && level <= props.unfoldedLevel) {
                        ret = true;
                    }
                }
                unfolded[node[props.valueField]] = ret;
            }
        });
        return unfolded;
    };
    TreeSelector.prototype.toggleUnfolded = function (node) {
        this.setState({
            addItem: null,
            unfolded: tslib_1.__assign({}, this.state.unfolded, (_a = {}, _a[node[this.props.valueField]] = !this.state.unfolded[node[this.props.valueField]], _a))
        });
        var _a;
    };
    TreeSelector.prototype.clearSelect = function () {
        var _this = this;
        this.setState({
            value: []
        }, function () {
            var _a = _this.props, joinValues = _a.joinValues, rootValue = _a.rootValue, onChange = _a.onChange;
            onChange(joinValues ? rootValue : []);
        });
    };
    TreeSelector.prototype.handleSelect = function (node, value) {
        var _this = this;
        this.setState({
            value: [node]
        }, function () {
            var _a = _this.props, joinValues = _a.joinValues, valueField = _a.valueField, onChange = _a.onChange;
            onChange(joinValues ? node[valueField] : node);
        });
    };
    TreeSelector.prototype.handleCheck = function (item, checked) {
        var _this = this;
        var props = this.props;
        var value = this.state.value.concat();
        var idx = value.indexOf(item);
        var onlyChildren = this.props.onlyChildren;
        if (checked) {
            ~idx || value.push(item);
            if (!props.cascade) {
                var children = item.children ? item.children.concat([]) : [];
                if (onlyChildren) {
                    // 父级选中的时候，子节点也都选中，但是自己不选中
                    !~idx && children.length && value.shift();
                    while (children.length) {
                        var child = children.shift();
                        var index = value.indexOf(child);
                        if (child.children) {
                            children.push.apply(children, child.children);
                        }
                        else {
                            ~index || value.push(child);
                        }
                    }
                }
                else {
                    // 只要父节点选择了,子节点就不需要了,全部去掉勾选.  withChildren时相反
                    while (children.length) {
                        var child = children.shift();
                        var index = value.indexOf(child);
                        if (~index) {
                            value.splice(index, 1);
                        }
                        if (props.withChildren) {
                            value.push(child);
                        }
                        if (child.children && child.children.length) {
                            children.push.apply(children, child.children);
                        }
                    }
                }
            }
        }
        else if (!checked) {
            ~idx && value.splice(idx, 1);
            if (!props.cascade && (props.withChildren || onlyChildren)) {
                var children = item.children ? item.children.concat([]) : [];
                while (children.length) {
                    var child = children.shift();
                    var index = value.indexOf(child);
                    if (~index) {
                        value.splice(index, 1);
                    }
                    if (child.children && child.children.length) {
                        children.push.apply(children, child.children);
                    }
                }
            }
        }
        this.setState({
            value: value
        }, function () {
            var _a = _this.props, joinValues = _a.joinValues, extractValue = _a.extractValue, valueField = _a.valueField, delimiter = _a.delimiter, onChange = _a.onChange;
            onChange(joinValues
                ? value.map(function (item) { return item[valueField]; }).join(delimiter)
                : extractValue
                    ? value.map(function (item) { return item[valueField]; })
                    : value);
        });
    };
    TreeSelector.prototype.handleAdd = function (item, isFolder) {
        var _a = this.props, addMode = _a.addMode, openAddDialog = _a.openAddDialog, valueField = _a.valueField;
        var unfolded = this.state.unfolded;
        if (addMode === 'dialog') {
            openAddDialog && openAddDialog(item ? item : null);
        }
        else if (addMode === 'normal') {
            // item 为 null 时为添加一级
            if (item) {
                // 添加时，默认折叠的文件夹需要展开
                if (isFolder && !unfolded[item[valueField]]) {
                    unfolded = tslib_1.__assign({}, unfolded, (_b = {}, _b[item[valueField]] = !unfolded[item[valueField]], _b));
                }
                this.setState({
                    addItem: item,
                    editItem: null,
                    unfolded: unfolded
                });
            }
            else {
                this.setState({
                    addTop: true,
                    editItem: null,
                    addItem: null
                });
            }
        }
        var _b;
    };
    TreeSelector.prototype.handleEdit = function (item) {
        var _a = this.props, editMode = _a.editMode, openEditDialog = _a.openEditDialog;
        var addItem = this.state.addItem;
        if (editMode === 'dialog') {
            openEditDialog && openEditDialog(item);
            addItem && this.setState({
                addItem: null
            });
        }
        else if (editMode === 'normal') {
            this.setState({
                editItem: item,
                addItem: null
            });
        }
    };
    TreeSelector.prototype.handleRemove = function (item) {
        var onRemove = this.props.onRemove;
        onRemove && onRemove(item);
    };
    TreeSelector.prototype.handleConfirmOnAdd = function () {
        var onAdd = this.props.onAdd;
        var _a = this.state, parent = _a.addItem, addingItem = _a.addingItem;
        onAdd && onAdd(tslib_1.__assign({}, addingItem, { parent: parent }));
        this.setState({
            addingItem: null,
            addItem: null,
            addTop: false
        });
    };
    TreeSelector.prototype.handleCancelOnAdd = function () {
        this.setState({
            addItem: null,
            addTop: false
        });
    };
    TreeSelector.prototype.handleConfirmOnEdit = function () {
        var onEdit = this.props.onEdit;
        var _a = this.state, editingItem = _a.editingItem, prevItem = _a.editItem;
        onEdit && onEdit(tslib_1.__assign({}, editingItem, { prev: prevItem }));
        this.setState({
            editingItem: null,
            editItem: null
        });
    };
    TreeSelector.prototype.handleCancelOnEdit = function () {
        this.setState({
            editItem: null
        });
    };
    TreeSelector.prototype.handleChangeOnAdd = function (value) {
        this.setState({
            addingItem: {
                label: value
            }
        });
    };
    TreeSelector.prototype.handleChangeOnEdit = function (item, value) {
        var editItem = this.state.editItem;
        this.setState({
            editingItem: tslib_1.__assign({}, item, { label: value || editItem['label'] })
        });
    };
    TreeSelector.prototype.renderList = function (list, value, uncheckable) {
        var _this = this;
        var _a = this.props, itemClassName = _a.itemClassName, showIcon = _a.showIcon, showRadio = _a.showRadio, multiple = _a.multiple, disabled = _a.disabled, _b = _a.nameField, nameField = _b === void 0 ? '' : _b, _c = _a.valueField, valueField = _c === void 0 ? '' : _c, _d = _a.iconField, iconField = _d === void 0 ? '' : _d, _e = _a.disabledField, disabledField = _e === void 0 ? '' : _e, cascade = _a.cascade, selfDisabledAffectChildren = _a.selfDisabledAffectChildren, onlyChildren = _a.onlyChildren, cx = _a.classnames, highlightTxt = _a.highlightTxt, data = _a.data, maxLength = _a.maxLength, minLength = _a.minLength, addable = _a.addable, editable = _a.editable, removable = _a.removable;
        var _f = this.state, addItem = _f.addItem, editItem = _f.editItem, unfolded = _f.unfolded, addTop = _f.addTop, stateValue = _f.value;
        var childrenChecked = 0;
        var ret = list.map(function (item, key) {
            if (!helper_1.isVisible(item, data)) {
                return null;
            }
            var checked = !!~value.indexOf(item);
            var selfDisabled = item[disabledField];
            var selfChecked = !!uncheckable || checked;
            var childrenItems = null;
            var tmpChildrenChecked = false;
            if (item.children && item.children.length) {
                childrenItems = _this.renderList(item.children, value, cascade
                    ? false
                    : uncheckable || (selfDisabledAffectChildren ? selfDisabled : false) || (multiple && checked));
                tmpChildrenChecked = !!childrenItems.childrenChecked;
                if (!selfChecked && onlyChildren && item.children.length === childrenItems.childrenChecked) {
                    selfChecked = true;
                }
                childrenItems = childrenItems.dom;
            }
            if (tmpChildrenChecked || checked) {
                childrenChecked++;
            }
            var nodeDisabled = !!uncheckable || !!disabled || selfDisabled;
            if (!nodeDisabled &&
                ((maxLength && !selfChecked && stateValue.length >= maxLength) ||
                    (minLength && selfChecked && stateValue.length <= minLength))) {
                nodeDisabled = true;
            }
            var checkbox = multiple ? (react_1.default.createElement("label", { className: cx("Checkbox Checkbox--checkbox Checkbox--sm") },
                react_1.default.createElement("input", { type: "checkbox", disabled: nodeDisabled, checked: selfChecked, onChange: function (e) { return _this.handleCheck(item, e.currentTarget.checked); } }),
                react_1.default.createElement("i", null))) : showRadio ? (react_1.default.createElement("label", { className: cx("Checkbox Checkbox--radio Checkbox--sm") },
                react_1.default.createElement("input", { type: "radio", disabled: nodeDisabled, checked: checked, onChange: function () { return _this.handleSelect(item); } }),
                react_1.default.createElement("i", null))) : null;
            var isLeaf = !item.children || !item.children.length;
            return (react_1.default.createElement("li", { key: key, className: cx("Tree-item " + (itemClassName || ''), {
                    'Tree-item--isLeaf': isLeaf
                }) },
                !editItem || helper_1.isObject(editItem) && editItem[valueField] !== item[valueField] ? (react_1.default.createElement("a", null,
                    !isLeaf ? (react_1.default.createElement("i", { onClick: function () { return _this.toggleUnfolded(item); }, className: cx('Tree-itemArrow', {
                            'is-folded': !unfolded[item[valueField]],
                        }) })) : null,
                    showIcon ? (react_1.default.createElement("i", { className: cx("Tree-itemIcon " + (item[iconField] ||
                            (childrenItems ? 'Tree-folderIcon' : 'Tree-leafIcon'))) })) : null,
                    checkbox,
                    react_1.default.createElement("span", { className: cx('Tree-itemText', {
                            'is-children-checked': multiple && !cascade && tmpChildrenChecked && !nodeDisabled,
                            'is-checked': checked,
                            'is-disabled': nodeDisabled,
                        }), onClick: function () {
                            return !nodeDisabled &&
                                (multiple ? _this.handleCheck(item, !selfChecked) : _this.handleSelect(item));
                        } }, highlightTxt ? Options_1.highlight(item[nameField], highlightTxt) : item[nameField]),
                    !nodeDisabled
                        && !addTop
                        && !addItem
                        && !editItem ? (react_1.default.createElement("span", { className: cx('Tree-item-icons') },
                        addable ? react_1.default.createElement(icons_1.Icon, { icon: "plus", className: "icon", onClick: function () { return _this.handleAdd(item, !isLeaf); } }) : null,
                        removable ? react_1.default.createElement(icons_1.Icon, { icon: "minus", className: "icon", onClick: function () { return _this.handleRemove(item); } }) : null,
                        editable ? react_1.default.createElement(icons_1.Icon, { icon: "pencil", className: "icon", onClick: function () { return _this.handleEdit(item); } }) : null)) : null)) : (react_1.default.createElement("div", { className: cx('Tree-item--isEdit') },
                    react_1.default.createElement("input", { defaultValue: item['label'], onChange: function (e) { return _this.handleChangeOnEdit(item, e.currentTarget.value); } }),
                    react_1.default.createElement(icons_1.Icon, { icon: "check", className: "icon", onClick: _this.handleConfirmOnEdit }),
                    react_1.default.createElement(icons_1.Icon, { icon: "close", className: "icon", onClick: _this.handleCancelOnEdit }))),
                ((childrenItems && unfolded[item[valueField]]) || addItem && (addItem[valueField] === item[valueField])) ? (react_1.default.createElement("ul", { className: cx('Tree-sublist') },
                    addItem && addItem[valueField] === item[valueField] ? (react_1.default.createElement("li", null,
                        react_1.default.createElement("input", { onChange: function (e) { return _this.handleChangeOnAdd(e.currentTarget.value); } }),
                        react_1.default.createElement(icons_1.Icon, { icon: "check", className: "icon", onClick: _this.handleConfirmOnAdd }),
                        react_1.default.createElement(icons_1.Icon, { icon: "close", className: "icon", onClick: _this.handleCancelOnAdd }))) : null,
                    childrenItems)) : null));
        });
        return {
            dom: ret,
            childrenChecked: childrenChecked
        };
    };
    TreeSelector.prototype.render = function () {
        var _this = this;
        var _a = this.props, className = _a.className, placeholder = _a.placeholder, hideRoot = _a.hideRoot, rootLabel = _a.rootLabel, showIcon = _a.showIcon, cx = _a.classnames, addable = _a.addable;
        var data = this.props.data;
        var _b = this.state, value = _b.value, addTop = _b.addTop;
        return (react_1.default.createElement("div", { className: cx("Tree " + (className || '')) }, data && data.length ? (react_1.default.createElement("ul", { className: cx('Tree-list') }, hideRoot ? (this.renderList(data, value, false).dom) : (react_1.default.createElement("li", { className: cx('Tree-item Tree-rootItem') },
            react_1.default.createElement("a", null,
                showIcon ? react_1.default.createElement("i", { className: cx('Tree-itemIcon Tree-rootIcon') }) : null,
                react_1.default.createElement("label", { className: cx('Tree-itemLabel', {
                        'is-checked': !value || !value.length
                    }) },
                    react_1.default.createElement("span", { className: cx('Tree-itemText'), onClick: this.clearSelect }, rootLabel))),
            addable ? (react_1.default.createElement("div", { className: cx('Tree-addTop') },
                !addTop ? (react_1.default.createElement("p", { onClick: function () { return _this.handleAdd(null, false); } },
                    react_1.default.createElement(icons_1.Icon, { icon: "plus", className: "icon" }),
                    react_1.default.createElement("span", null, "\u6DFB\u52A0\u4E00\u7EA7"))) : null,
                addTop ? (react_1.default.createElement("div", { className: cx('Tree-addTop-input') },
                    react_1.default.createElement("input", { onChange: function (e) { return _this.handleChangeOnAdd(e.currentTarget.value); } }),
                    react_1.default.createElement(icons_1.Icon, { icon: "check", className: "icon", onClick: this.handleConfirmOnAdd }),
                    react_1.default.createElement(icons_1.Icon, { icon: "close", className: "icon", onClick: this.handleCancelOnAdd }))) : null)) : null,
            react_1.default.createElement("ul", { className: cx('Tree-sublist') }, this.renderList(data, value, false).dom))))) : (react_1.default.createElement("div", { className: cx('Tree-placeholder') }, placeholder))));
    };
    TreeSelector.defaultProps = {
        showIcon: true,
        initiallyOpen: true,
        unfoldedLevel: 0,
        showRadio: false,
        multiple: false,
        disabled: false,
        withChildren: false,
        onlyChildren: false,
        nameField: 'name',
        valueField: 'value',
        iconField: 'icon',
        unfoldedField: 'unfolded',
        foldedField: 'foled',
        disabledField: 'disabled',
        joinValues: true,
        extractValue: false,
        delimiter: ',',
        hideRoot: true,
        rootLabel: '顶级',
        rootValue: 0,
        cascade: false,
        selfDisabledAffectChildren: true
    };
    tslib_1.__decorate([
        helper_1.autobind,
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", [Object]),
        tslib_1.__metadata("design:returntype", void 0)
    ], TreeSelector.prototype, "toggleUnfolded", null);
    tslib_1.__decorate([
        helper_1.autobind,
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", []),
        tslib_1.__metadata("design:returntype", void 0)
    ], TreeSelector.prototype, "clearSelect", null);
    tslib_1.__decorate([
        helper_1.autobind,
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", [Object, Object]),
        tslib_1.__metadata("design:returntype", void 0)
    ], TreeSelector.prototype, "handleSelect", null);
    tslib_1.__decorate([
        helper_1.autobind,
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", [Object, Boolean]),
        tslib_1.__metadata("design:returntype", void 0)
    ], TreeSelector.prototype, "handleCheck", null);
    tslib_1.__decorate([
        helper_1.autobind,
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", [typeof (_a = typeof Checkboxes_1.Option !== "undefined" && Checkboxes_1.Option) === "function" && _a || Object, Boolean]),
        tslib_1.__metadata("design:returntype", void 0)
    ], TreeSelector.prototype, "handleAdd", null);
    tslib_1.__decorate([
        helper_1.autobind,
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", [typeof (_b = typeof Checkboxes_1.Option !== "undefined" && Checkboxes_1.Option) === "function" && _b || Object]),
        tslib_1.__metadata("design:returntype", void 0)
    ], TreeSelector.prototype, "handleEdit", null);
    tslib_1.__decorate([
        helper_1.autobind,
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", [typeof (_c = typeof Checkboxes_1.Option !== "undefined" && Checkboxes_1.Option) === "function" && _c || Object]),
        tslib_1.__metadata("design:returntype", void 0)
    ], TreeSelector.prototype, "handleRemove", null);
    tslib_1.__decorate([
        helper_1.autobind,
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", []),
        tslib_1.__metadata("design:returntype", void 0)
    ], TreeSelector.prototype, "handleConfirmOnAdd", null);
    tslib_1.__decorate([
        helper_1.autobind,
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", []),
        tslib_1.__metadata("design:returntype", void 0)
    ], TreeSelector.prototype, "handleCancelOnAdd", null);
    tslib_1.__decorate([
        helper_1.autobind,
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", []),
        tslib_1.__metadata("design:returntype", void 0)
    ], TreeSelector.prototype, "handleConfirmOnEdit", null);
    tslib_1.__decorate([
        helper_1.autobind,
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", []),
        tslib_1.__metadata("design:returntype", void 0)
    ], TreeSelector.prototype, "handleCancelOnEdit", null);
    tslib_1.__decorate([
        helper_1.autobind,
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", [String]),
        tslib_1.__metadata("design:returntype", void 0)
    ], TreeSelector.prototype, "handleChangeOnAdd", null);
    tslib_1.__decorate([
        helper_1.autobind,
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", [typeof (_d = typeof Checkboxes_1.Option !== "undefined" && Checkboxes_1.Option) === "function" && _d || Object, String]),
        tslib_1.__metadata("design:returntype", void 0)
    ], TreeSelector.prototype, "handleChangeOnEdit", null);
    tslib_1.__decorate([
        helper_1.autobind,
        tslib_1.__metadata("design:type", Function),
        tslib_1.__metadata("design:paramtypes", [typeof (_e = typeof Checkboxes_1.Options !== "undefined" && Checkboxes_1.Options) === "function" && _e || Object, Array, Boolean]),
        tslib_1.__metadata("design:returntype", Object)
    ], TreeSelector.prototype, "renderList", null);
    return TreeSelector;
    var _a, _b, _c, _d, _e;
}(react_1.default.Component));
exports.TreeSelector = TreeSelector;
exports.default = theme_1.themeable(TreeSelector);
//# sourceMappingURL=./components/Tree.js.map
