import { __assign, __extends, __spreadArray } from "tslib";
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { Component } from 'react';
import classnames from 'classnames';
import { AnimateHeight } from '../utils/component/AnimateHeight';
import Checkbox from '../checkbox';
import { InlineLoading } from '../loading/InlineLoading';
import createStateByProps from './utils/createStateByProps';
import correctMark from './utils/correctMark';
import correctExpand from './utils/correctExpand';
import Icon from '../icon';
import { EASE_IN_CUBIC, EASE_OUT_CUBIC } from '../utils/timingFunctions';
import { TreeContent } from './TreeContent';
var SINGLE_INDENT_WIDTH = 12;
var SWITCHER_WIDTH_MAP = {
    small: 16,
    medium: 20,
    large: 24,
};
var Tree = (function (_super) {
    __extends(Tree, _super);
    function Tree(props) {
        var _this = _super.call(this, props) || this;
        _this.setSelectKeyState = function (data, target) {
            var _a, _b;
            (_b = (_a = _this.props).onSelect) === null || _b === void 0 ? void 0 : _b.call(_a, data, target);
            if (!_this.isSelectControlled) {
                _this.setState({ selectedKey: data.id });
            }
        };
        _this.state = __assign({ prevProps: props, loadingNode: [] }, createStateByProps(props));
        return _this;
    }
    Object.defineProperty(Tree.prototype, "isSelectControlled", {
        get: function () {
            return 'selectedKey' in this.props;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(Tree.prototype, "selectedKey", {
        get: function () {
            return this.isSelectControlled
                ? this.props.selectedKey
                : this.state.selectedKey;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(Tree.prototype, "disabledSelectedKeys", {
        get: function () {
            var _a = this.props, disableSelectedStrictly = _a.disableSelectedStrictly, disabledSelectedKeys = _a.disabledSelectedKeys;
            var rootInfoMap = this.state.rootInfoMap;
            if (!disabledSelectedKeys || disabledSelectedKeys.length === 0) {
                return [];
            }
            if (!disableSelectedStrictly) {
                return disabledSelectedKeys;
            }
            var keys = [];
            disabledSelectedKeys.forEach(function (key) {
                keys.push.apply(keys, rootInfoMap[key].rootIncludeIds);
            });
            return keys;
        },
        enumerable: false,
        configurable: true
    });
    Tree.getDerivedStateFromProps = function (nextProps, state) {
        var prevProps = state.prevProps;
        if (nextProps === prevProps) {
            return null;
        }
        if (nextProps.data !== prevProps.data ||
            nextProps.renderKey !== prevProps.renderKey ||
            nextProps.expandAll !== prevProps.expandAll ||
            nextProps.loadMore !== prevProps.loadMore) {
            var formatData = createStateByProps(nextProps);
            var expandNode = formatData.expandNode;
            if (nextProps.expandAll === prevProps.expandAll) {
                expandNode = correctExpand(state, formatData);
            }
            return __assign(__assign({ prevProps: nextProps }, formatData), { expandNode: expandNode });
        }
        if (nextProps.checkable) {
            var newState = {};
            if (prevProps.disabledCheckedKeys !== nextProps.disabledCheckedKeys) {
                newState.disabledNode = correctMark(nextProps.disabledCheckedKeys, state.rootInfoMap);
            }
            if (prevProps.checkedKeys !== nextProps.checkedKeys) {
                newState.checkedNode = correctMark(nextProps.checkedKeys, state.rootInfoMap, newState.disabledNode || state.disabledNode);
                newState.checkedNode = newState.checkedNode.filter(function (id) {
                    return (state.disabledNode.indexOf(id) === -1 ||
                        state.checkedNode.indexOf(id) > -1);
                });
            }
            return __assign(__assign({}, newState), { prevProps: nextProps });
        }
        return {
            prevProps: nextProps,
        };
    };
    Tree.prototype.handleExpandIconClick = function (root, e) {
        var _this = this;
        var id = this.state.renderKey.id;
        var _a = this.props, loadMore = _a.loadMore, foldable = _a.foldable;
        if (!foldable) {
            return;
        }
        var loadingNode = this.state.loadingNode;
        if (loadMore) {
            if (!root.children || root.children.length === 0) {
                e.persist();
                var nextLoadingNode_1 = loadingNode.concat(root[id]);
                this.setState({ loadingNode: nextLoadingNode_1 });
                loadMore(root)
                    .then(function () {
                    _this.setState({
                        loadingNode: nextLoadingNode_1.filter(function (x) { return x !== root[id]; }),
                    });
                    _this.handleExpand(root);
                })
                    .catch(function () {
                    _this.setState({
                        loadingNode: nextLoadingNode_1.filter(function (x) { return x !== root[id]; }),
                    });
                });
                return;
            }
        }
        this.handleExpand(root);
    };
    Tree.prototype.handleExpand = function (root) {
        var onExpand = this.props.onExpand;
        var expandNode = this.state.expandNode;
        var id = this.state.renderKey.id;
        var activeId = root[id];
        var newExpandNode = expandNode.slice();
        var isClose = true;
        if (expandNode.indexOf(activeId) > -1) {
            newExpandNode = expandNode.filter(function (expandId) { return expandId !== activeId; });
        }
        else {
            isClose = false;
            newExpandNode.push(activeId);
        }
        this.setState({
            expandNode: newExpandNode,
        });
        if (onExpand) {
            onExpand(root, {
                isExpanded: !isClose,
            });
        }
    };
    Tree.prototype.handleCheckboxClick = function (root) {
        var onCheck = this.props.onCheck;
        var _a = this.state, checkedNode = _a.checkedNode, disabledNode = _a.disabledNode, rootInfoMap = _a.rootInfoMap, renderKey = _a.renderKey;
        var rootId = root[renderKey.id];
        if (checkedNode.indexOf(rootId) > -1) {
            checkedNode = checkedNode.filter(function (id) {
                if (id === rootId) {
                    return false;
                }
                if (disabledNode.indexOf(id) > -1) {
                    return true;
                }
                if (rootInfoMap[id].rootIncludeIds.indexOf(rootId) > -1) {
                    return false;
                }
                if (rootInfoMap[rootId].rootIncludeIds.indexOf(id) > -1) {
                    return false;
                }
                return true;
            });
        }
        else {
            checkedNode = correctMark(__spreadArray([rootId], checkedNode), rootInfoMap, disabledNode);
        }
        var helperInfo = {
            currentRoot: root,
            disabled: disabledNode.map(function (id) { return rootInfoMap[id].root; }),
            all: [],
            top: [],
            bottom: [],
        };
        checkedNode.forEach(function (id) {
            helperInfo.all.push(rootInfoMap[id].root);
            if (!rootInfoMap[id].parentId ||
                checkedNode.indexOf(rootInfoMap[rootInfoMap[id].parentId].id) === -1) {
                helperInfo.top.push(rootInfoMap[id].root);
            }
            if (rootInfoMap[id].rootIncludeIds.length === 1 ||
                rootInfoMap[id].rootIncludeIds.every(function (child) { return checkedNode.indexOf(child) === -1; })) {
                helperInfo.bottom.push(rootInfoMap[id].root);
            }
        });
        onCheck && onCheck(checkedNode, helperInfo);
    };
    Tree.prototype.renderSwitcher = function (root) {
        var _this = this;
        var _a = this.state, loadingNode = _a.loadingNode, id = _a.renderKey.id;
        return (_jsx(_Fragment, { children: loadingNode.includes(root[id]) ? (_jsx(InlineLoading, { loading: true }, void 0)) : (_jsx(Icon, { className: "zent-tree-switcher", type: "right", onClick: function (e) {
                    e.stopPropagation();
                    _this.handleExpandIconClick(root, e);
                } }, void 0)) }, void 0));
    };
    Tree.prototype.renderContent = function (root, isExpanded) {
        var title = this.state.renderKey.title;
        var _a = this.props, render = _a.render, onlyShowOneLine = _a.onlyShowOneLine;
        return (_jsx(TreeContent, __assign({ showPop: onlyShowOneLine }, { children: render ? render(root, isExpanded) : root[title] }), void 0));
    };
    Tree.prototype.renderCheckbox = function (root) {
        var checkable = this.props.checkable;
        var _a = this.state, checkedNode = _a.checkedNode, disabledNode = _a.disabledNode, rootInfoMap = _a.rootInfoMap, renderKey = _a.renderKey;
        if (!checkable) {
            return null;
        }
        var rootId = root[renderKey.id];
        var checked = checkedNode.indexOf(rootId) > -1;
        var countChild = rootInfoMap[rootId].rootIncludeIds.filter(function (id) { return disabledNode.indexOf(id) === -1; });
        var halfChecked = !!(!checked &&
            countChild.length &&
            countChild.some(function (id) { return checkedNode.indexOf(id) > -1; }));
        return (_jsx(Checkbox, { onChange: this.handleCheckboxClick.bind(this, root), checked: checked, disabled: disabledNode.indexOf(rootId) > -1, indeterminate: halfChecked, width: root[renderKey.title] }, void 0));
    };
    Tree.prototype.renderOperations = function (root, isExpanded) {
        var id = this.state.renderKey.id;
        var opts = this.props.operations;
        if (opts) {
            var optNodes = opts.map(function (opt) {
                var shouldRender = opt.shouldRender || (function () { return true; });
                return (shouldRender(root) && (_jsxs("span", __assign({ onClick: opt.action.bind(null, root, isExpanded), className: "zent-tree-operation", "data-zv": 'v10.0.11' }, { children: [typeof opt.icon === 'string' ? (_jsx("i", { className: opt.icon, "data-zv": 'v10.0.11' }, void 0)) : (opt.icon), ' ', opt.name] }), opt.name + "-" + root[id])));
            });
            return _jsx("div", __assign({ className: "zent-tree-operation-container", "data-zv": 'v10.0.11' }, { children: optNodes }), void 0);
        }
        return null;
    };
    Tree.prototype.renderTreeNodes = function (roots, layers) {
        var _this = this;
        if (layers === void 0) { layers = 0; }
        var _a = this.props, autoExpandOnSelect = _a.autoExpandOnSelect, selectable = _a.selectable, onlyShowOneLine = _a.onlyShowOneLine, size = _a.size;
        var _b = this.state, expandNode = _b.expandNode, rootInfoMap = _b.rootInfoMap, _c = _b.renderKey, id = _c.id, children = _c.children;
        if (roots && roots.length > 0) {
            return roots.map(function (root) {
                var rootId = root[id];
                var isSelected = rootId === _this.selectedKey;
                var isDisabled = _this.disabledSelectedKeys.includes(rootId);
                var isShowChildren = expandNode.indexOf(rootId) > -1;
                var barClassName = classnames('zent-tree-bar', {
                    'zent-tree-bar--off': !isShowChildren,
                    'zent-tree-bar--selected': isSelected,
                    'zent-tree-bar--disabled': isDisabled,
                });
                var indentWidth = layers * SINGLE_INDENT_WIDTH +
                    +!rootInfoMap[rootId].isParent * SWITCHER_WIDTH_MAP[size];
                return (_jsxs("li", __assign({ "data-zv": 'v10.0.11' }, { children: [_jsxs("div", __assign({ className: barClassName, onClick: function (e) {
                                autoExpandOnSelect && _this.handleExpand(root);
                                if (selectable && !isDisabled) {
                                    _this.setSelectKeyState(root, e.currentTarget);
                                }
                            }, "data-zv": 'v10.0.11' }, { children: [_jsx("span", { className: "zent-tree-bar__indent", style: { width: indentWidth + "px" }, "data-zv": 'v10.0.11' }, void 0), rootInfoMap[rootId].isParent && _this.renderSwitcher(root), _jsxs("div", __assign({ className: classnames('zent-tree-node', {
                                        'zent-tree-node--one-line': onlyShowOneLine,
                                    }), "data-zv": 'v10.0.11' }, { children: [_this.renderCheckbox(root), _this.renderContent(root, isShowChildren), _this.renderOperations(root, isShowChildren)] }), void 0)] }), void 0), root[children] && root[children].length > 0 && (_jsx(AnimateHeight, __assign({ appear: true, duration: 200, height: isShowChildren ? 'auto' : 0, easing: isShowChildren ? EASE_IN_CUBIC : EASE_OUT_CUBIC }, { children: _jsx("ul", __assign({ className: "zent-tree-child", "data-zv": 'v10.0.11' }, { children: _this.renderTreeNodes(root[children], layers + 1) }), "ul-" + rootId) }), void 0))] }), rootId));
            });
        }
        return null;
    };
    Tree.prototype.render = function () {
        var _a;
        var _b = this.props, commonStyle = _b.commonStyle, size = _b.size;
        var tree = this.state.tree;
        var classNames = classnames('zent-tree', (_a = {},
            _a["zent-tree-" + size] = size !== 'medium',
            _a));
        return (_jsx("ul", __assign({ className: classNames, style: commonStyle, "data-zv": 'v10.0.11' }, { children: this.renderTreeNodes(tree) }), void 0));
    };
    Tree.defaultProps = {
        autoExpandOnSelect: false,
        dataType: 'tree',
        foldable: true,
        checkable: false,
        selectable: true,
        size: 'medium',
    };
    return Tree;
}(Component));
export { Tree };
export default Tree;
