"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CompositeTreeNode = exports.TreeNode = exports.BranchOperatorStatus = void 0;
exports.spliceArray = spliceArray;
/* eslint-disable @typescript-eslint/prefer-for-of */
const ide_utils_1 = require("@opensumi/ide-utils");
const types_1 = require("../types");
const { Path } = ide_utils_1.path;
/**
 * 裁剪数组
 *
 * @param arr 裁剪数组
 * @param start 起始位置
 * @param deleteCount 删除或替换位置
 * @param items 插入的数组
 */
function spliceArray(arr, start, deleteCount = 0, items) {
    const a = arr.slice(0);
    a.splice(start, deleteCount, ...(items || []));
    return a;
}
var BranchOperatorStatus;
(function (BranchOperatorStatus) {
    BranchOperatorStatus[BranchOperatorStatus["EXPANDED"] = 1] = "EXPANDED";
    BranchOperatorStatus[BranchOperatorStatus["SHRINKED"] = 2] = "SHRINKED";
})(BranchOperatorStatus || (exports.BranchOperatorStatus = BranchOperatorStatus = {}));
class TreeNode {
    static is(node) {
        return !!node && 'depth' in node && 'name' in node && 'path' in node && 'id' in node;
    }
    static getTreeNodeById(id) {
        return TreeNode.idToTreeNode.get(id);
    }
    static getTreeNodeByPath(path) {
        return TreeNode.pathToTreeNode.get(path);
    }
    static setTreeNode(id, path, node) {
        TreeNode.idToTreeNode.set(id, node);
        TreeNode.pathToTreeNode.set(path, node);
    }
    static removeTreeNode(id, path) {
        TreeNode.idToTreeNode.delete(id);
        TreeNode.pathToTreeNode.delete(path);
    }
    static getIdByPath(path) {
        return TreeNode.pathToId.get(path);
    }
    static setIdByPath(path, id) {
        return TreeNode.pathToId.set(path, id);
    }
    static getGlobalTreeState(path) {
        let state = TreeNode.pathToGlobalTreeState.get(path);
        if (!state) {
            state = {
                isExpanding: false,
                isLoadingPath: false,
                isRefreshing: false,
                refreshCancelToken: new ide_utils_1.CancellationTokenSource(),
                loadPathCancelToken: new ide_utils_1.CancellationTokenSource(),
            };
        }
        return state;
    }
    static setGlobalTreeState(path, updateState) {
        let state = TreeNode.pathToGlobalTreeState.get(path);
        if (!state) {
            state = {
                isExpanding: false,
                isLoadingPath: false,
                isRefreshing: false,
                refreshCancelToken: new ide_utils_1.CancellationTokenSource(),
                loadPathCancelToken: new ide_utils_1.CancellationTokenSource(),
            };
        }
        state = {
            ...state,
            ...updateState,
        };
        TreeNode.pathToGlobalTreeState.set(path, state);
        return state;
    }
    constructor(tree, parent, watcher, optionalMetadata) {
        this._uid = TreeNode.nextId();
        this._parent = parent;
        this._tree = tree;
        this._disposed = false;
        this._visible = true;
        this._metadata = { ...(optionalMetadata || {}) };
        this._depth = parent ? parent.depth + 1 : 0;
        if (watcher) {
            this._watcher = watcher;
        }
        else if (parent) {
            this._watcher = parent.watcher;
        }
    }
    get disposed() {
        return this._disposed;
    }
    /**
     * 获取基础信息
     */
    get depth() {
        return this._depth;
    }
    get parent() {
        return this._parent;
    }
    set parent(node) {
        this._parent = node;
        // 节点 `parent` 变化，更新当前节点的 `path` 属性
        this._path = '';
    }
    get type() {
        return types_1.TreeNodeType.TreeNode;
    }
    get id() {
        return this._uid;
    }
    set id(id) {
        this._uid = id;
    }
    get displayName() {
        return this.name;
    }
    /**
     * 由于 Tree 对于唯一路径的 path 的依赖
     * 在传入 `name` 值时必须保证其在路径上的唯一性
     * 一般不建议手动管理 `name`，采用默认值即可
     */
    get name() {
        if (!this.parent) {
            return `root_${this.id}`;
        }
        return this.getMetadata('name') || String(this.id);
    }
    set name(name) {
        this.addMetadata('name', name);
        // 节点 `name` 变化，更新当前节点的 `path` 属性
        this._path = '';
    }
    // 节点绝对路径
    get path() {
        if (!this._path) {
            if (!this.parent) {
                this._path = new Path(`${Path.separator}${this.name}`).toString();
            }
            else {
                this._path = new Path(this.parent.path).join(this.name).toString();
            }
        }
        return this._path;
    }
    get accessibilityInformation() {
        return {
            label: this.name,
            role: 'treeitem',
        };
    }
    getMetadata(withKey) {
        if (withKey === 'name' && !this._metadata[withKey]) {
            this._metadata[withKey] = String(TreeNode.nextId());
        }
        return this._metadata[withKey];
    }
    addMetadata(withKey, value) {
        if (!(withKey in this._metadata)) {
            this._metadata[withKey] = value;
            this._watcher.notifyDidChangeMetadata(this, {
                type: types_1.MetadataChangeType.Added,
                key: withKey,
                prevValue: void 0,
                value,
            });
        }
        else {
            const prevValue = this._metadata[withKey];
            this._metadata[withKey] = value;
            this._watcher.notifyDidChangeMetadata(this, { type: types_1.MetadataChangeType.Updated, key: withKey, prevValue, value });
        }
    }
    removeMetadata(withKey) {
        if (withKey in this._metadata) {
            const prevValue = this._metadata[withKey];
            delete this._metadata[withKey];
            this._watcher.notifyDidChangeMetadata(this, {
                type: types_1.MetadataChangeType.Removed,
                key: withKey,
                prevValue,
                value: void 0,
            });
        }
    }
    /**
     * 这里的move操作可能为移动，也可能为重命名
     *
     * @param {ICompositeTreeNode} to
     * @param {string} [name=this.name]
     * @returns
     * @memberof TreeNode
     */
    mv(to, name = this.name) {
        // 一个普通节点必含有父节点，根节点不允许任何操作
        const prevParent = this._parent;
        if (to === null || !CompositeTreeNode.is(to)) {
            this.parent = undefined;
            this.dispose();
            return;
        }
        const didChangeParent = prevParent !== to;
        const prevPath = this.path;
        this._depth = to.depth + 1;
        if (didChangeParent || name !== this.name) {
            this.name = name;
            if (didChangeParent) {
                this._watcher.notifyWillChangeParent(this, prevParent, to);
            }
            if (this.parent) {
                this.parent.unlinkItem(this, true);
                this.parent = to;
                this.parent.insertItem(this);
            }
            if (didChangeParent) {
                this._watcher.notifyDidChangeParent(this, prevParent, to);
            }
        }
        if (this.path !== prevPath) {
            this._watcher.notifyDidChangePath(this);
        }
    }
    get visible() {
        return this._visible;
    }
    setVisible(b) {
        this._visible = b;
        return this;
    }
    dispose() {
        if (this._disposed) {
            return;
        }
        TreeNode.removeTreeNode(this.id, this.path);
        this._disposed = true;
        this._watcher.notifyDidDispose(this);
    }
}
exports.TreeNode = TreeNode;
TreeNode.nextId = (() => {
    let id = 0;
    return () => id++;
})();
TreeNode.idToTreeNode = new Map();
TreeNode.pathToTreeNode = new Map();
TreeNode.pathToId = new Map();
// 每颗树都只会在根节点上绑定一个可取消的对象，即同个时间点只能存在一个改变树数据结构的事情
TreeNode.pathToGlobalTreeState = new Map();
class CompositeTreeNode extends TreeNode {
    static defaultSortComparator(a, b) {
        if (a.constructor === b.constructor) {
            return a.name > b.name ? 1 : a.name < b.name ? -1 : 0;
        }
        return CompositeTreeNode.is(a) ? -1 : CompositeTreeNode.is(b) ? 1 : 0;
    }
    static is(node) {
        return !!node && 'children' in node;
    }
    static isRoot(node) {
        return CompositeTreeNode.is(node) && !node.parent;
    }
    generatorWatcher() {
        const emitter = new ide_utils_1.Emitter();
        const onEventChanges = emitter.event;
        const disposeCollection = new ide_utils_1.DisposableCollection();
        const terminateWatch = (path) => {
            this.watchEvents.delete(path);
        };
        const watcher = {
            notifyWillProcessWatchEvent: (target, event) => {
                emitter.fire({ type: types_1.TreeNodeEvent.WillProcessWatchEvent, args: [target, event] });
            },
            notifyWillChangeParent: (target, prevParent, newParent) => {
                emitter.fire({ type: types_1.TreeNodeEvent.WillChangeParent, args: [target, prevParent, newParent] });
            },
            notifyDidChangeParent: (target, prevParent, newParent) => {
                emitter.fire({ type: types_1.TreeNodeEvent.DidChangeParent, args: [target, prevParent, newParent] });
            },
            notifyDidDispose: (target) => {
                emitter.fire({ type: types_1.TreeNodeEvent.DidDispose, args: [target] });
            },
            notifyDidProcessWatchEvent: (target, event) => {
                emitter.fire({ type: types_1.TreeNodeEvent.DidProcessWatchEvent, args: [target, event] });
            },
            notifyDidChangePath: (target) => {
                emitter.fire({ type: types_1.TreeNodeEvent.DidChangePath, args: [target] });
            },
            notifyWillChangeExpansionState: (target, nowExpanded) => {
                const isVisible = this.isItemVisibleAtSurface(target);
                emitter.fire({ type: types_1.TreeNodeEvent.WillChangeExpansionState, args: [target, nowExpanded, isVisible] });
            },
            notifyDidChangeExpansionState: (target, nowExpanded) => {
                const isVisible = this.isItemVisibleAtSurface(target);
                emitter.fire({ type: types_1.TreeNodeEvent.DidChangeExpansionState, args: [target, nowExpanded, isVisible] });
            },
            notifyDidChangeMetadata: (target, change) => {
                emitter.fire({ type: types_1.TreeNodeEvent.DidChangeMetadata, args: [target, change] });
            },
            notifyDidUpdateBranch: () => {
                emitter.fire({ type: types_1.TreeNodeEvent.BranchDidUpdate, args: [] });
            },
            notifyWillResolveChildren: (target, nowExpanded) => {
                emitter.fire({ type: types_1.TreeNodeEvent.WillResolveChildren, args: [target, nowExpanded] });
            },
            notifyDidResolveChildren: (target, nowExpanded) => {
                emitter.fire({ type: types_1.TreeNodeEvent.DidResolveChildren, args: [target, nowExpanded] });
            },
            // 监听所有事件
            on: (event, callback) => {
                const dispose = onEventChanges((data) => {
                    if (data.type === event) {
                        callback(...data.args);
                    }
                });
                disposeCollection.push(dispose);
                return dispose;
            },
            // 监听Watch事件变化
            onWatchEvent: (path, callback) => {
                const terminator = terminateWatch;
                this.watchEvents.set(path, { terminator, callback });
                return terminator;
            },
            dispose: disposeCollection,
        };
        return watcher;
    }
    // parent 为undefined即表示该节点为根节点
    constructor(tree, parent, watcher, optionalMetadata) {
        super(tree, parent, watcher, optionalMetadata);
        this._children = null;
        this._lock = false;
        this.refreshThrottler = new ide_utils_1.ThrottledDelayer(CompositeTreeNode.REFRESH_DELAY);
        this.toRefreshPathQueue = new Set();
        /**
         * 处理 Watch 事件，同时可通过外部手动调 g用节点更新函数进行节点替换，这里为通用的事件管理
         * 如： transferItem，insertItem, unlinkItem等
         * @private
         * @memberof CompositeTreeNode
         */
        this.handleWatchEvent = async (event) => {
            this.watcher.notifyWillProcessWatchEvent(this, event);
            switch (event.type) {
                case types_1.WatchEvent.Moved: {
                    const { oldPath, newPath } = event;
                    if (typeof oldPath !== 'string') {
                        throw new TypeError('Expected oldPath to be a string');
                    }
                    if (typeof newPath !== 'string') {
                        throw new TypeError('Expected newPath to be a string');
                    }
                    if (Path.isRelative(oldPath)) {
                        throw new TypeError('oldPath must be absolute');
                    }
                    if (Path.isRelative(newPath)) {
                        throw new TypeError('newPath must be absolute');
                    }
                    this.transferItem(oldPath, newPath);
                    break;
                }
                case types_1.WatchEvent.Added: {
                    const { node } = event;
                    if (!TreeNode.is(node)) {
                        throw new TypeError('Expected node to be a TreeNode');
                    }
                    this.insertItem(node);
                    break;
                }
                case types_1.WatchEvent.Removed: {
                    const { path } = event;
                    const pathObject = new Path(path);
                    const dirName = pathObject.dir.toString();
                    const name = pathObject.base.toString();
                    if (dirName === this.path && !!this.children) {
                        const item = this.children.find((c) => c.name === name);
                        if (item) {
                            this.unlinkItem(item);
                        }
                    }
                    break;
                }
                default:
                    // 如果当前变化的节点已在数据视图（并非滚动到不可见区域）中不可见，则将该节点折叠，待下次更新即可，
                    if (!this.isItemVisibleAtRootSurface(this)) {
                        this.isExpanded = false;
                        this._children = null;
                    }
                    else {
                        await this.refresh();
                    }
                    break;
            }
            this.watcher.notifyDidProcessWatchEvent(this, event);
        };
        this.isExpanded = parent ? false : true;
        this._branchSize = 0;
        if (!parent) {
            this.watchEvents = new Map();
            // 为根节点创建监听器
            this._watcher = this.generatorWatcher();
            this._root = this;
            TreeNode.setTreeNode(this.id, this.path, this);
        }
        else {
            this._watcher = parent.watcher;
        }
    }
    // 重载 name 的 getter/setter，路径改变时需要重新监听文件节点变化
    set name(name) {
        const prevPath = this.path;
        if (!CompositeTreeNode.isRoot(this) && typeof this.watchTerminator === 'function') {
            this.watchTerminator(prevPath);
            this.addMetadata('name', name);
            this.watchTerminator = this.watcher.onWatchEvent(this.path, this.handleWatchEvent);
        }
        else {
            this.addMetadata('name', name);
        }
        // 节点 `name` 变化，更新当前节点的 `path` 属性
        this._path = '';
    }
    get name() {
        // 根节点保证路径不重复
        if (!this.parent) {
            return `root_${this.id}`;
        }
        return this.getMetadata('name');
    }
    // 作为根节点唯一的watcher需要在生成新节点的时候传入
    get watcher() {
        return this._watcher;
    }
    get type() {
        return types_1.TreeNodeType.CompositeTreeNode;
    }
    get children() {
        return this._children;
    }
    get expanded() {
        return this.isExpanded;
    }
    /**
     * 当前可见的分支数量
     *
     * 当节点为展开状态时，其整个分支（递归展平）由上一级的分支（根（位于数据层可见）或处于折叠状态的分支）拥有
     * 当节点为折叠状态时，其整个分支（递归展平）由其上一级父目录展开该节点
     *
     * @readonly
     * @memberof CompositeTreeNode
     */
    get branchSize() {
        return this._branchSize;
    }
    /**
     * 获取当前节点的分支数，一般为顶层节点，如Root上获取
     *
     * @readonly
     * @memberof CompositeTreeNode
     */
    get flattenedBranch() {
        return this._flattenedBranch;
    }
    get lock() {
        return this._lock;
    }
    get root() {
        if ((0, ide_utils_1.isUndefined)(this._root)) {
            this._root = this.getRoot() || null;
        }
        return this._root;
    }
    getRoot() {
        let root = this.parent;
        while (root && root.parent) {
            root = root.parent;
        }
        return root;
    }
    /**
     * 确保此“目录”的子级已加载（不影响“展开”状态）
     * 如果子级已经加载，则返回的Promise将立即解决
     * 否则，将发出重新加载请求并返回Promise
     * 一旦返回的Promise.resolve，“CompositeTreeNode＃children” 便可以访问到对于节点
     */
    async ensureLoaded(token) {
        if (this._children) {
            return;
        }
        return await this.hardReloadChildren(token);
    }
    // 展开节点
    async setExpanded(ensureVisible = true, quiet = false, isOwner = true, token) {
        if (this.disposed) {
            return;
        }
        // 根节点不可折叠
        if (CompositeTreeNode.isRoot(this)) {
            return;
        }
        if (this.isExpanded) {
            return;
        }
        if (isOwner) {
            const state = TreeNode.getGlobalTreeState(this.path);
            state.loadPathCancelToken.cancel();
            state.refreshCancelToken.cancel();
            TreeNode.setGlobalTreeState(this.path, {
                isExpanding: true,
            });
        }
        this.isExpanded = true;
        if (this._children === null) {
            this._watcher.notifyWillResolveChildren(this, this.isExpanded);
            await this.hardReloadChildren(token);
            this._watcher.notifyDidResolveChildren(this, this.isExpanded);
            // 检查其是否展开；可能同时执行了 setCollapsed 方法
            if (!this.isExpanded || (token === null || token === void 0 ? void 0 : token.isCancellationRequested)) {
                if (isOwner) {
                    TreeNode.setGlobalTreeState(this.path, {
                        isExpanding: false,
                    });
                }
                return;
            }
        }
        if (ensureVisible && this.parent && CompositeTreeNode.is(this.parent)) {
            /**
             * 在传入 ensureVisible = true 时，这里传入的 token 不能取消所有副作用
             * 故在使用 ensureVisible = true 时必须保证 `setExpanded` 与 `setCollapsed` 的独立性
             * 如需要 `await node.setExpanded(true)` 后再执行 `node.setCollapsed()`
             */
            await this.parent.setExpanded(true, !quiet, false, token);
        }
        if (token === null || token === void 0 ? void 0 : token.isCancellationRequested) {
            if (isOwner) {
                TreeNode.setGlobalTreeState(this.path, {
                    isExpanding: false,
                });
            }
            return;
        }
        if (this.isExpanded) {
            this._watcher.notifyWillChangeExpansionState(this, true);
            // 与根节点合并分支
            this.expandBranch(this, quiet);
            this._watcher.notifyDidChangeExpansionState(this, true);
        }
        if (isOwner) {
            TreeNode.setGlobalTreeState(this.path, {
                isExpanding: false,
            });
            TreeNode.setTreeNode(this.id, this.path, this);
        }
    }
    // 获取当前节点下所有展开的节点路径
    getAllExpandedNodePath() {
        var _a, _b;
        const paths = [];
        let start = 0;
        if (!CompositeTreeNode.isRoot(this)) {
            // 找到节点位置下标，向下进一步查找展开目录
            start = ((_a = this.root) === null || _a === void 0 ? void 0 : _a.getIndexAtTreeNodeId(this.id)) + 1;
        }
        const end = start + this.branchSize;
        for (let i = start; i < end; i++) {
            const node = (_b = this.root) === null || _b === void 0 ? void 0 : _b.getTreeNodeAtIndex(i);
            if (CompositeTreeNode.is(node) && node.expanded) {
                paths.push(node.path);
            }
        }
        return paths;
    }
    // 获取当前节点下所有折叠的节点路径
    getAllCollapsedNodePath() {
        let paths = [];
        if (this.children) {
            for (let i = 0; i < this.children.length; i++) {
                const child = this.children[i];
                if (!CompositeTreeNode.is(child)) {
                    continue;
                }
                if (child.isExpanded) {
                    paths = paths.concat(child.getAllCollapsedNodePath());
                }
                else {
                    paths.push(child.path);
                }
            }
            return paths;
        }
        else {
            return paths;
        }
    }
    /**
     * 处理节点数据，让节点重新加载子节点及初始化 flattenedBranch
     * @param token CancellationToken
     */
    async resolveChildrens(token) {
        var _a, _b, _c;
        let childrens = this.children;
        let expandedPaths = [];
        try {
            childrens = (await this._tree.resolveChildren(this)) || [];
        }
        catch (e) {
            childrens = [];
        }
        if (token === null || token === void 0 ? void 0 : token.isCancellationRequested) {
            return false;
        }
        const flatTree = new Array(childrens.length);
        this._children = Array(childrens.length);
        for (let i = 0; i < childrens.length; i++) {
            const child = childrens[i];
            // 如果存在上一次缓存的节点，则使用缓存节点的 ID
            child.id = TreeNode.getIdByPath(child.path) || child.id;
            this._children[i] = child;
            TreeNode.setIdByPath(child.path, child.id);
        }
        (_a = this._children) === null || _a === void 0 ? void 0 : _a.sort(this._tree.sortComparator || CompositeTreeNode.defaultSortComparator);
        for (let i = 0; i < childrens.length; i++) {
            flatTree[i] = this._children[i].id;
        }
        const expandedChilds = [];
        for (let i = 0, len = ((_b = this.children) === null || _b === void 0 ? void 0 : _b.length) || 0; i < len; i++) {
            const subChild = (_c = this.children) === null || _c === void 0 ? void 0 : _c[i];
            if (CompositeTreeNode.is(subChild) && subChild.expanded) {
                const paths = await subChild.resolveChildrens(token);
                if (paths) {
                    expandedPaths = expandedPaths.concat(paths);
                }
                if (token === null || token === void 0 ? void 0 : token.isCancellationRequested) {
                    return;
                }
                expandedChilds.push(subChild);
            }
        }
        this._branchSize = flatTree.length;
        this.setFlattenedBranch(flatTree);
        for (let i = 0; i < expandedChilds.length; i++) {
            const child = expandedChilds[i];
            child.expandBranch(child, true);
        }
        return expandedPaths.concat(expandedChilds.map((child) => child.path.toString()));
    }
    updateTreeNodeCache(child) {
        var _a;
        TreeNode.setTreeNode(child.id, child.path, child);
        if (CompositeTreeNode.is(child) && child.expanded && ((_a = child.children) === null || _a === void 0 ? void 0 : _a.length)) {
            for (let i = 0; i < child.children.length; i++) {
                const subChild = child.children[i];
                this.updateTreeNodeCache(subChild);
            }
        }
    }
    /**
     * 静默刷新子节点, 即不触发分支更新事件
     * @param toExpandPaths 待展开的路径
     * @param token CancellationToken
     * @param origin 当 this === origin 时，说明此节点为调用的源头节点
     */
    async refreshTreeNodeByPaths(toExpandPaths = this.getAllExpandedNodePath(), token, origin) {
        if (!CompositeTreeNode.is(this)) {
            return;
        }
        // 如果某次刷新操作被取消，则下次刷新依旧使用上一次刷新的展开目录进行刷新
        let toExpandPath;
        const originChildren = this.children;
        let childrens = this.children || [];
        if (this.expanded) {
            if (this === origin) {
                try {
                    childrens = (await this._tree.resolveChildren(this)) || [];
                }
                catch (e) {
                    childrens = [];
                }
                if (token === null || token === void 0 ? void 0 : token.isCancellationRequested) {
                    return;
                }
                if (!this.expanded) {
                    // 当请求刷新节点时，如果该节点已经不应该被处理，则清理 Children
                    // 下次再被展开时便会自动更新 Children 最新内容
                    if (this.children) {
                        // 清理子节点，等待下次展开时更新
                        if (!!this.children && this.parent) {
                            for (let i = 0; i < this.children.length; i++) {
                                const child = this.children[i];
                                child.dispose();
                            }
                            this._children = null;
                        }
                    }
                    return;
                }
            }
            while ((toExpandPath = toExpandPaths.shift())) {
                const isRelative = toExpandPath.indexOf(`${this.path}${Path.separator}`) > -1;
                if (!isRelative) {
                    if (toExpandPath === this.path) {
                        toExpandPath = undefined;
                    }
                    break;
                }
                const child = childrens === null || childrens === void 0 ? void 0 : childrens.find((child) => child.path === toExpandPath);
                // 对于压缩情况的路径需要额外处理一下
                // 如果这里加载的路径是 a/b/c, 有可能目前只加载到 a/b
                if (!child) {
                    if (!childrens || childrens.length === 0) {
                        break;
                    }
                    for (let i = 0; i < childrens.length; i++) {
                        const child = childrens[i];
                        const isInclude = toExpandPath.indexOf(`${child.path}${Path.separator}`) === 0; // 展开路径包含子节点路径
                        if (isInclude && CompositeTreeNode.is(child)) {
                            // 包含压缩节点的情况
                            if (!CompositeTreeNode.is(child)) {
                                // 说明此节点为非折叠节点时不处理
                                continue;
                            }
                            child.isExpanded = true;
                            // 加载路径包含当前判断路径，尝试加载该节点再匹配
                            const extraExpandedPaths = await child.resolveChildrens(token);
                            if (token === null || token === void 0 ? void 0 : token.isCancellationRequested) {
                                return;
                            }
                            if (extraExpandedPaths) {
                                toExpandPaths = toExpandPaths.filter((path) => !extraExpandedPaths.find((a) => a === path));
                            }
                            if (child.path !== toExpandPath && !toExpandPaths.includes(child.path)) {
                                toExpandPaths.unshift(toExpandPath);
                            }
                            if (toExpandPaths.length > 0) {
                                // 不需要重新加载压缩节点的子节点内容
                                toExpandPaths =
                                    (await child.refreshTreeNodeByPaths([...toExpandPaths], token, origin)) || [];
                                if (token === null || token === void 0 ? void 0 : token.isCancellationRequested) {
                                    return;
                                }
                            }
                            break;
                        }
                    }
                }
                else if (CompositeTreeNode.is(child)) {
                    // 如果节点默认展开，则忽略后续操作
                    if (!child.expanded) {
                        child.isExpanded = true;
                        const extraExpandedPaths = await child.resolveChildrens(token);
                        if (token === null || token === void 0 ? void 0 : token.isCancellationRequested) {
                            return;
                        }
                        if (extraExpandedPaths) {
                            toExpandPaths = toExpandPaths.filter((path) => !extraExpandedPaths.find((a) => a.includes(path)));
                        }
                        if (toExpandPaths.length > 0 && !(token === null || token === void 0 ? void 0 : token.isCancellationRequested)) {
                            toExpandPaths =
                                (await child.refreshTreeNodeByPaths([...toExpandPaths], token, origin)) || [];
                            if (token === null || token === void 0 ? void 0 : token.isCancellationRequested) {
                                return;
                            }
                        }
                    }
                }
            }
            if (toExpandPath) {
                // 仍然存在需要进一步处理的待展开路径
                toExpandPaths.unshift(toExpandPath);
                if (this === origin) {
                    // 说明待展开的路径已经不存在，直接处理子节点
                    if (originChildren) {
                        this.shrinkBranch(this, true);
                        for (let i = 0; i < originChildren.length; i++) {
                            const child = originChildren[i];
                            child === null || child === void 0 ? void 0 : child.dispose();
                        }
                    }
                    const expandedChilds = [];
                    const flatTree = new Array(childrens.length);
                    this._children = Array(childrens.length);
                    for (let i = 0; i < childrens.length; i++) {
                        const child = childrens[i];
                        // 如果存在上一次缓存的节点，则使用缓存节点的 ID
                        child.id = TreeNode.getIdByPath(child.path) || child.id;
                        this._children[i] = child;
                        TreeNode.setIdByPath(child.path, child.id);
                        if (CompositeTreeNode.is(child) && child.expanded) {
                            expandedChilds.push(child);
                        }
                    }
                    this._children.sort(this._tree.sortComparator || CompositeTreeNode.defaultSortComparator);
                    for (let i = 0; i < childrens.length; i++) {
                        flatTree[i] = this._children[i].id;
                    }
                    this._branchSize = flatTree.length;
                    this.setFlattenedBranch(flatTree, true);
                    this.watcher.notifyDidUpdateBranch();
                }
                if (this.parent !== origin) {
                    // 将所有子节点合并至第二层 Children 上，减少后续递归拼接带来额外成本
                    this.expandBranch(this, true);
                }
                return toExpandPaths;
            }
            else if (CompositeTreeNode.isRoot(this)) {
                if (this.children) {
                    this.shrinkBranch(this, true);
                    for (let i = 0; i < this.children.length; i++) {
                        const child = this.children[i];
                        child === null || child === void 0 ? void 0 : child.dispose();
                    }
                }
                const expandedChilds = [];
                const otherChilds = [];
                const flatTree = new Array(childrens.length);
                this._children = Array(childrens.length);
                for (let i = 0; i < childrens.length; i++) {
                    const child = childrens[i];
                    // 如果存在上一次缓存的节点，则使用缓存节点的 ID
                    child.id = TreeNode.getIdByPath(child.path) || child.id;
                    this._children[i] = child;
                    TreeNode.setIdByPath(child.path, child.id);
                    if (CompositeTreeNode.is(child) && child.expanded) {
                        if (!child.children) {
                            await child.resolveChildrens(token);
                            if (token === null || token === void 0 ? void 0 : token.isCancellationRequested) {
                                return;
                            }
                        }
                        expandedChilds.push(child);
                    }
                    else {
                        otherChilds.push(child);
                    }
                }
                this._children.sort(this._tree.sortComparator || CompositeTreeNode.defaultSortComparator);
                for (let i = 0; i < childrens.length; i++) {
                    flatTree[i] = this._children[i].id;
                }
                this._branchSize = flatTree.length;
                this.setFlattenedBranch(flatTree, true);
                for (let i = 0; i < expandedChilds.length; i++) {
                    const child = expandedChilds[i];
                    child.expandBranch(child, true);
                    this.updateTreeNodeCache(child);
                }
                for (let i = 0; i < otherChilds.length; i++) {
                    const child = otherChilds[i];
                    this.updateTreeNodeCache(child);
                }
                // 清理上一次监听函数
                if (typeof this.watchTerminator === 'function') {
                    this.watchTerminator(this.path);
                }
                this.watchTerminator = this.watcher.onWatchEvent(this.path, this.handleWatchEvent);
                this.watcher.notifyDidUpdateBranch();
            }
            else {
                // 非根节点刷新的情况
                const expandedChilds = [];
                if (this === origin) {
                    // 通知节点更新
                    if (this.children) {
                        // 重置旧的节点分支
                        this.shrinkBranch(this, true);
                    }
                    if (this.children) {
                        for (let i = 0, len = this.children.length; i < len; i++) {
                            const child = this.children[i];
                            child.dispose();
                        }
                    }
                    const flatTree = new Array(childrens.length);
                    this._children = Array(childrens.length);
                    for (let i = 0, len = childrens.length; i < len; i++) {
                        const child = childrens[i];
                        child.id = TreeNode.getIdByPath(child.path) || child.id;
                        this._children[i] = child;
                        TreeNode.setIdByPath(child.path, child.id);
                        if (CompositeTreeNode.is(child) && child.expanded) {
                            expandedChilds.push(child);
                        }
                        this.updateTreeNodeCache(child);
                    }
                    this._children.sort(this._tree.sortComparator || CompositeTreeNode.defaultSortComparator);
                    for (let i = 0; i < childrens.length; i++) {
                        flatTree[i] = this._children[i].id;
                    }
                    this._branchSize = flatTree.length;
                    this.setFlattenedBranch(flatTree);
                    for (let i = 0; i < expandedChilds.length; i++) {
                        const child = expandedChilds[i];
                        child.expandBranch(child, true);
                    }
                }
                else {
                    for (let i = 0; i < childrens.length; i++) {
                        const child = childrens[i];
                        if (child.expanded) {
                            expandedChilds.push(child);
                        }
                    }
                }
                for (let i = 0; i < expandedChilds.length; i++) {
                    const child = expandedChilds[i];
                    child.expandBranch(child, true);
                }
                if (typeof this.watchTerminator === 'function') {
                    this.watchTerminator(this.path);
                }
                this.watchTerminator = this.watcher.onWatchEvent(this.path, this.handleWatchEvent);
                if (this === origin) {
                    this.expandBranch(this);
                }
            }
        }
        else {
            // 仅需处理存在子节点的情况，否则将会影响刷新后的节点长度
            if (this.children) {
                // 清理子节点，等待下次展开时更新
                if (!!this.children && this.parent) {
                    // eslint-disable-next-line @typescript-eslint/prefer-for-of
                    for (let i = 0, len = this.children.length; i < len; i++) {
                        const child = this.children[i];
                        child.dispose();
                    }
                    this._children = null;
                }
            }
            return;
        }
    }
    async expandedAll(collapsedPaths = this.getAllCollapsedNodePath()) {
        // 仅根节点使用
        if (!CompositeTreeNode.isRoot(this)) {
            return;
        }
        collapsedPaths = collapsedPaths.sort((a, b) => Path.pathDepth(a) - Path.pathDepth(b));
        let path;
        while (collapsedPaths.length > 0) {
            path = collapsedPaths.pop();
            const item = TreeNode.getTreeNodeByPath(path);
            if (CompositeTreeNode.is(item)) {
                await item.setExpanded(false, true);
            }
        }
        // 通知分支树已更新
        this.watcher.notifyDidUpdateBranch();
    }
    async collapsedAll(expandedPaths = this.getAllExpandedNodePath()) {
        // 仅根节点使用
        if (!CompositeTreeNode.isRoot(this)) {
            return;
        }
        expandedPaths = expandedPaths.sort((a, b) => Path.pathDepth(a) - Path.pathDepth(b));
        let path;
        while (expandedPaths.length > 0) {
            path = expandedPaths.pop();
            const item = TreeNode.getTreeNodeByPath(path);
            if (CompositeTreeNode.is(item)) {
                item.setCollapsed(true);
            }
        }
        // 通知分支树已更新
        this.watcher.notifyDidUpdateBranch();
    }
    // 折叠节点
    setCollapsed(quiet = false) {
        // 根节点不可折叠
        if (CompositeTreeNode.isRoot(this) || this.disposed) {
            return;
        }
        if (!this.isExpanded) {
            return;
        }
        const state = TreeNode.getGlobalTreeState(this.path);
        if (state.isExpanding) {
            // 当节点处于加载子节点过程时，尽管为展开状态，但此时不应该支持折叠节点
            return;
        }
        state.loadPathCancelToken.cancel();
        state.refreshCancelToken.cancel();
        this._watcher.notifyWillChangeExpansionState(this, false);
        if (this._children && this.parent) {
            // 从根节点裁剪分支
            this.shrinkBranch(this, quiet);
        }
        this.isExpanded = false;
        TreeNode.setTreeNode(this.id, this.path, this);
        this._watcher.notifyDidChangeExpansionState(this, false);
    }
    mv(to, name = this.name) {
        const prevPath = this.path;
        super.mv(to, name);
        if (typeof this.watchTerminator === 'function') {
            this.watchTerminator(prevPath);
            this.watchTerminator = this.watcher.onWatchEvent(this.path, this.handleWatchEvent);
        }
        // 同时移动过子节点
        if (this.children) {
            for (let i = 0; i < this.children.length; i++) {
                const child = this.children[i];
                child.mv(child.parent, child.name);
            }
        }
    }
    /**
     * 在节点中插入新的节点
     *
     * 直接调用此方法将不会触发onWillHandleWatchEvent和onDidHandleWatchEvent事件
     */
    insertItem(item) {
        if (item.parent !== this) {
            item.mv(this, item.name);
            return;
        }
        if (this.children) {
            for (let i = 0; i < this.children.length; i++) {
                // path / id 是节点唯一标识
                if (this.children[i].path === item.path) {
                    this.children[i] = item;
                    return;
                }
            }
        }
        const branchSizeIncrease = 1 + (item instanceof CompositeTreeNode && item.expanded ? item._branchSize : 0);
        if (this._children) {
            this._children.push(item);
            this._children.sort(this._tree.sortComparator || CompositeTreeNode.defaultSortComparator);
        }
        this._branchSize += branchSizeIncrease;
        let master = this;
        // 如果该节点无叶子节点，则继续往上查找合适的插入位置
        while (!master._flattenedBranch) {
            if (master.parent) {
                master = master.parent;
                master._branchSize += branchSizeIncrease;
            }
        }
        if (!this._children) {
            return;
        }
        let relativeInsertionIndex = this._children.indexOf(item);
        let absInsertionIndex;
        const leadingSibling = this._children[relativeInsertionIndex - 1];
        if (leadingSibling) {
            const siblingIdx = master._flattenedBranch.indexOf(leadingSibling.id);
            relativeInsertionIndex =
                siblingIdx +
                    (leadingSibling instanceof CompositeTreeNode && leadingSibling.expanded ? leadingSibling._branchSize : 0);
        }
        else {
            relativeInsertionIndex = master._flattenedBranch.indexOf(this.id);
        }
        if (relativeInsertionIndex === -1) {
            if (this._branchSize === 1) {
                // 在空Tree中插入节点时，相对插入位置为0
                relativeInsertionIndex = 0;
            }
        }
        // 非空Tree情况下需要+1，为了容纳自身节点位置，在插入节点下方插入新增节点
        absInsertionIndex = relativeInsertionIndex + 1;
        // 空 Tree 情况下需要重置为 0，避免设置 Uint32Array 时超出范围
        if (master._flattenedBranch.length === 0) {
            absInsertionIndex = 0;
        }
        let branch = [item.id];
        if (item instanceof CompositeTreeNode && item.expanded && item._flattenedBranch) {
            branch = branch.concat(item._flattenedBranch);
            item.setFlattenedBranch(null);
        }
        master.setFlattenedBranch(spliceArray(master._flattenedBranch, absInsertionIndex, 0, branch));
        TreeNode.setTreeNode(item.id, item.path, item);
        return item;
    }
    /**
     * 从父节点中移除节点
     *
     * 直接调用此方法将不会触发onWillHandleWatchEvent和onDidHandleWatchEvent事件
     */
    unlinkItem(item, reparenting) {
        var _a;
        if (!this._children) {
            return;
        }
        const idx = this._children.indexOf(item);
        if (idx === -1) {
            return;
        }
        // 当删除时父节点已不存在界面上时，跳过插入操作
        if (!this.isItemVisibleAtRootSurface(this)) {
            return;
        }
        (_a = this._children) === null || _a === void 0 ? void 0 : _a.splice(idx, 1);
        const branchSizeDecrease = 1 + (item instanceof CompositeTreeNode && item.expanded ? item._branchSize : 0);
        this._branchSize -= branchSizeDecrease;
        // 逐级往上查找节点的父节点，并沿途裁剪分支数
        let master = this;
        while (!master._flattenedBranch) {
            if (master.parent) {
                master = master.parent;
                master._branchSize -= branchSizeDecrease;
            }
        }
        const removalBeginIdx = master._flattenedBranch.indexOf(item.id);
        if (removalBeginIdx === -1) {
            return;
        }
        if (item instanceof CompositeTreeNode && item.expanded) {
            item.setFlattenedBranch(master._flattenedBranch.slice(removalBeginIdx + 1, removalBeginIdx + branchSizeDecrease));
        }
        master.setFlattenedBranch(spliceArray(master._flattenedBranch, removalBeginIdx, branchSizeDecrease));
        if (!reparenting && item.parent === this) {
            item.mv(null);
        }
    }
    /**
     * 转换节点路径
     */
    transferItem(oldPath, newPath) {
        var _a;
        const oldP = new Path(oldPath);
        const from = oldP.dir.toString();
        if (from !== this.path) {
            return;
        }
        const name = oldP.base.toString();
        const item = (_a = this._children) === null || _a === void 0 ? void 0 : _a.find((c) => c.name === name);
        if (!item) {
            return;
        }
        const newP = new Path(newPath);
        const to = newP.dir.toString();
        const destDir = to === from ? this : TreeNode.getTreeNodeByPath(to);
        if (!CompositeTreeNode.is(destDir)) {
            this.unlinkItem(item);
            return;
        }
        item.mv(destDir, newP.base.toString());
        return item;
    }
    dispose() {
        // 如果存在对应文件路径下的监听，同样需要清理掉
        if (this.watchEvents) {
            const watcher = this.watchEvents.get(this.path);
            if (watcher) {
                watcher.terminator();
            }
            this.watchEvents.clear();
        }
        if (this._children) {
            // 移除后应该折叠，因为下次初始化默认值为折叠，否则将会导致下次插入异常
            this.isExpanded = false;
            this._children.forEach((child) => {
                child.dispose();
            });
            this._children = null;
            this._flattenedBranch = null;
        }
        super.dispose();
    }
    /**
     * 设置扁平化的分支信息
     */
    setFlattenedBranch(leaves, withoutNotify) {
        this._flattenedBranch = leaves;
        // Root节点才通知更新
        if (CompositeTreeNode.isRoot(this) && !withoutNotify) {
            this.watcher.notifyDidUpdateBranch();
        }
    }
    /**
     * 展开分支节点
     * @param branch 分支节点
     */
    expandBranch(branch, withoutNotify) {
        if (this !== branch) {
            // 但节点为展开状态时进行裁剪
            if (branch._flattenedBranch) {
                this._branchSize += branch._branchSize;
            }
        }
        // 当前节点为折叠状态，更新分支信息
        if (this !== branch && this._flattenedBranch) {
            const injectionStartIdx = this._flattenedBranch.indexOf(branch.id) + 1;
            if (injectionStartIdx === 0) {
                // 中途发生了branch更新事件，此时的_flattenedBranch可能已被更新，即查找不到branch.id
                // 这种情况在父节点发生了多路径目录的创建定位动作下更易复现
                // 例：文件树在执行a/b/c定位操作时需要请求三次数据，而更新操作可能只需要一次
                // 导致就算更新操作后置执行，也可能比定位操作先执行完，同时将_flattenedBranch更新
                // 最终导致此处查询不到对应节点，下面的shrinkBranch同样可能有相同问题，如点击折叠全部功能时
                return;
            }
            this.setFlattenedBranch(spliceArray(this._flattenedBranch, injectionStartIdx, 0, branch._flattenedBranch), withoutNotify);
            // 取消展开分支对于分支的所有权，即最终只会有顶部Root拥有所有分支信息
            branch.setFlattenedBranch(null, withoutNotify);
        }
        else if (this.parent) {
            this.parent.expandBranch(branch, withoutNotify);
        }
    }
    /**
     * 清理分支节点
     * @param branch 分支节点
     */
    shrinkBranch(branch, withoutNotify) {
        if (this !== branch) {
            // 这里的`this`实际上为父节点
            // `this`的分支大小没有改变，仍然具有相同数量的叶子，但是从父级参照系（即根节点）来看，其分支缩小了
            this._branchSize -= branch._branchSize;
        }
        if (this !== branch && this._flattenedBranch) {
            const removalStartIdx = this._flattenedBranch.indexOf(branch.id) + 1;
            if (removalStartIdx === 0) {
                // 中途发生了branch更新事件，此时的_flattenedBranch可能已被更新，即查找不到branch.id
                return;
            }
            // 返回分支对于分支信息所有权，即将折叠的节点信息再次存储于折叠了的节点中
            branch.setFlattenedBranch(this._flattenedBranch.slice(removalStartIdx, removalStartIdx + branch._branchSize), withoutNotify);
            this.setFlattenedBranch(spliceArray(this._flattenedBranch, removalStartIdx, branch._flattenedBranch ? branch._flattenedBranch.length : 0), withoutNotify);
        }
        else if (this.parent) {
            this.parent.shrinkBranch(branch, withoutNotify);
        }
    }
    /**
     * 加载子节点信息
     * 当返回值为 true 时，正常加载完子节点并同步到数据结构中
     * 返回值为 false 时，加载节点的过程被中断
     *
     * @memberof CompositeTreeNode
     */
    async hardReloadChildren(token) {
        let rawItems;
        const oldPath = this.path;
        try {
            // ! `this.path` maybe changed after `resolveChildren` in file tree compact mode
            rawItems = (await this._tree.resolveChildren(this)) || [];
        }
        catch (e) {
            rawItems = [];
        }
        // 当获取到新的子节点时，如果当前节点正处于非展开状态时，忽略后续裁切逻辑
        // 后续的 expandBranch 也不应该被响应
        if (!this.expanded || (token === null || token === void 0 ? void 0 : token.isCancellationRequested)) {
            return false;
        }
        if (this.path !== oldPath) {
            // do some clean up
            TreeNode.setGlobalTreeState(oldPath, {
                isExpanding: false,
                isLoadingPath: false,
                isRefreshing: false,
            });
        }
        const expandedChilds = [];
        const flatTree = new Array(rawItems.length);
        const tempChildren = new Array(rawItems.length);
        for (let i = 0; i < rawItems.length; i++) {
            const child = rawItems[i];
            child.id = TreeNode.getIdByPath(child.path) || child.id;
            tempChildren[i] = child;
            TreeNode.setIdByPath(child.path, child.id);
            if (CompositeTreeNode.is(child) && child.expanded) {
                if (!child.children) {
                    await child.resolveChildrens(token);
                }
                if (token === null || token === void 0 ? void 0 : token.isCancellationRequested) {
                    return false;
                }
                expandedChilds.push(child);
            }
        }
        tempChildren.sort(this._tree.sortComparator || CompositeTreeNode.defaultSortComparator);
        for (let i = 0; i < rawItems.length; i++) {
            flatTree[i] = tempChildren[i].id;
        }
        if (this.children) {
            this.shrinkBranch(this);
        }
        if (this.children) {
            for (let i = 0; i < this.children.length; i++) {
                const child = this.children[i];
                // The Child maybe `undefined`.
                child === null || child === void 0 ? void 0 : child.dispose();
            }
        }
        for (let i = 0; i < tempChildren.length; i++) {
            this.updateTreeNodeCache(tempChildren[i]);
        }
        this._children = tempChildren;
        this._branchSize = flatTree.length;
        this.setFlattenedBranch(flatTree);
        for (let i = 0; i < expandedChilds.length; i++) {
            const child = expandedChilds[i];
            child.expandBranch(child, true);
        }
        // 清理上一次监听函数
        if (typeof this.watchTerminator === 'function') {
            this.watchTerminator(this.path);
        }
        this.watchTerminator = this.watcher.onWatchEvent(this.path, this.handleWatchEvent);
        return true;
    }
    moveNode(oldPath, newPath) {
        if (typeof oldPath !== 'string') {
            throw new TypeError('Expected oldPath to be a string');
        }
        if (typeof newPath !== 'string') {
            throw new TypeError('Expected newPath to be a string');
        }
        if (Path.isRelative(oldPath)) {
            throw new TypeError('oldPath must be absolute');
        }
        if (Path.isRelative(newPath)) {
            throw new TypeError('newPath must be absolute');
        }
        return this.transferItem(oldPath, newPath);
    }
    addNode(node) {
        if (!TreeNode.is(node)) {
            throw new TypeError('Expected node to be a TreeNode');
        }
        return this.insertItem(node);
    }
    removeNode(path) {
        const pathObject = new Path(path);
        const dirName = pathObject.dir.toString();
        const name = pathObject.base.toString();
        if (dirName === this.path && !!this.children) {
            const item = this.children.find((c) => c.name === name);
            if (item) {
                this.unlinkItem(item);
            }
        }
    }
    // 当没有传入具体路径时，使用当前展开目录作为刷新路径
    async refresh(tokenSource, target) {
        if (!CompositeTreeNode.isRoot(this)) {
            // 刷新操作只能从根节点进行，便于对重复的刷新操作进行合并
            return await this.root.refresh(tokenSource, this);
        }
        const state = TreeNode.getGlobalTreeState(this.path);
        if (state.isLoadingPath || state.isExpanding) {
            return;
        }
        let token;
        if (tokenSource && !tokenSource.token.isCancellationRequested) {
            TreeNode.setGlobalTreeState(this.path, {
                isRefreshing: true,
                refreshCancelToken: tokenSource,
            });
            token = tokenSource.token;
        }
        else {
            if (state.refreshCancelToken.token.isCancellationRequested) {
                const refreshCancelToken = new ide_utils_1.CancellationTokenSource();
                TreeNode.setGlobalTreeState(this.path, {
                    isRefreshing: true,
                    refreshCancelToken,
                });
                token = refreshCancelToken.token;
            }
            else {
                token = state.refreshCancelToken.token;
            }
        }
        this.toRefreshPathQueue.add((target || this).path);
        await this.refreshThrottler.trigger(() => this.doRefresh(token));
        TreeNode.setGlobalTreeState(this.path, {
            isRefreshing: false,
        });
    }
    async doRefresh(token) {
        const target = this.getRefreshNode() || this;
        if (!CompositeTreeNode.is(target)) {
            return;
        }
        const paths = target.getAllExpandedNodePath();
        await target.refreshTreeNodeByPaths(paths, token, target);
    }
    getRefreshNode() {
        let paths = Array.from(this.toRefreshPathQueue);
        this.toRefreshPathQueue.clear();
        if (!paths.length) {
            return this.root;
        }
        // 根据路径层级深度进行排序
        paths = paths.sort((a, b) => {
            const depthA = Path.pathDepth(a);
            const depthB = Path.pathDepth(b);
            return depthA - depthB;
        });
        if (paths.length === 1 || Path.pathDepth(paths[0]) === 1) {
            // 说明刷新队列中包含根节点，直接返回根节点进行刷新
            return TreeNode.getTreeNodeByPath(paths[0]);
        }
        const sortedPaths = paths.map((p) => new Path(p));
        let rootPath = sortedPaths[0];
        for (let i = 1, len = sortedPaths.length; i < len; i++) {
            if (rootPath.isEqualOrParent(sortedPaths[i])) {
                continue;
            }
            else {
                while (!rootPath.isRoot) {
                    rootPath = rootPath.dir;
                    if (!rootPath || rootPath.isEqualOrParent(sortedPaths[i])) {
                        break;
                    }
                }
            }
        }
        if (rootPath) {
            return TreeNode.getTreeNodeByPath(rootPath.toString());
        }
        return this.root;
    }
    isItemVisibleAtRootSurface(node) {
        let parent = node;
        while (parent.parent) {
            parent = parent.parent;
        }
        return parent.isItemVisibleAtSurface(node);
    }
    /**
     * 检查节点是否可见，而不是被隐藏在节点中
     *
     * 这里的可见并不表示节点在当前视图中可见，而是在用户滚动到特定位置便可看见
     *
     * 隐藏在节点中可能的原因为其父节点中有一个以上处于折叠状态
     */
    isItemVisibleAtSurface(item) {
        if (item === this) {
            return true;
        }
        return !!this._flattenedBranch && this._flattenedBranch.indexOf(item.id) > -1;
    }
    transformToRelativePath(path) {
        const { splitPath } = Path;
        const pathFlag = splitPath(path);
        pathFlag.shift();
        return pathFlag;
    }
    /**
     * 根据路径展开节点树
     * @memberof CompositeTreeNode
     */
    async loadTreeNodeByPath(path, quiet = false) {
        if (!CompositeTreeNode.isRoot(this)) {
            return;
        }
        const state = TreeNode.getGlobalTreeState(this.path);
        if (state.isExpanding) {
            return;
        }
        state.refreshCancelToken.cancel();
        state.loadPathCancelToken.cancel();
        const loadPathCancelToken = new ide_utils_1.CancellationTokenSource();
        TreeNode.setGlobalTreeState(this.path, {
            isLoadingPath: true,
            loadPathCancelToken,
        });
        const token = loadPathCancelToken.token;
        const flattenedBranchChilds = [];
        const { splitPath, isRelative } = Path;
        const pathFlag = isRelative(path) ? splitPath(path) : this.transformToRelativePath(path);
        if (pathFlag.length === 0) {
            TreeNode.setGlobalTreeState(this.path, {
                isLoadingPath: false,
            });
            return this;
        }
        if (!this.children) {
            await this.ensureLoaded(token);
        }
        if (token.isCancellationRequested) {
            TreeNode.setGlobalTreeState(this.path, {
                isLoadingPath: false,
            });
            return;
        }
        let next = this._children;
        let preItem;
        let preItemPath = '';
        let name;
        while (next && (name = pathFlag.shift())) {
            let item = next.find((c) => c.name.indexOf(name) === 0);
            if (item) {
                if (CompositeTreeNode.is(item)) {
                    item._watcher.notifyWillChangeExpansionState(item, true);
                    item.isExpanded = true;
                    if (!item.children) {
                        await item.resolveChildrens(token);
                        if (token.isCancellationRequested) {
                            TreeNode.setGlobalTreeState(this.path, {
                                isLoadingPath: false,
                            });
                            return;
                        }
                    }
                    flattenedBranchChilds.push(item);
                    item._watcher.notifyDidChangeExpansionState(item, true);
                }
                if (pathFlag.length === 0) {
                    preItem = item;
                    break;
                }
            }
            // 可能展开后路径发生了变化, 需要重新处理一下当前加载路径
            if (!item && preItem) {
                const compactPath = splitPath(preItem.name).slice(1);
                if (compactPath[0] === name) {
                    compactPath.shift();
                    while (compactPath.length > 0) {
                        if (compactPath[0] === pathFlag[0]) {
                            compactPath.shift();
                            pathFlag.shift();
                        }
                        else {
                            break;
                        }
                    }
                    name = pathFlag.shift();
                    item = next.find((c) => c.name.indexOf(name) === 0);
                }
            }
            // 最终加载到的路径节点
            if (!item || (!CompositeTreeNode.is(item) && pathFlag.length > 0)) {
                break;
            }
            if (CompositeTreeNode.is(item)) {
                const isCompactName = item.name.indexOf(Path.separator) > 0;
                if (isCompactName) {
                    const compactPath = splitPath(item.name).slice(1);
                    while (compactPath.length > 0) {
                        if (compactPath[0] === pathFlag[0]) {
                            compactPath.shift();
                            pathFlag.shift();
                        }
                        else {
                            break;
                        }
                    }
                }
                if (!item._children) {
                    preItemPath = item.path;
                    if (CompositeTreeNode.is(item)) {
                        item.isExpanded = true;
                        if (!item.children) {
                            await item.resolveChildrens(token);
                            if (token.isCancellationRequested) {
                                TreeNode.setGlobalTreeState(this.path, {
                                    isLoadingPath: false,
                                });
                                return;
                            }
                        }
                        flattenedBranchChilds.push(item);
                    }
                }
                if (item && pathFlag.length === 0) {
                    preItem = item;
                    break;
                }
                else {
                    if (!!preItemPath && preItemPath !== item.path) {
                        // 说明此时已发生了路径压缩，如从 a -> a/b/c
                        // 需要根据路径变化移除对应的展开路径, 这里只需考虑短变长场景
                        const prePaths = splitPath(preItemPath);
                        const nextPaths = splitPath(item.path);
                        if (nextPaths.length > prePaths.length) {
                            pathFlag.splice(0, nextPaths.length - prePaths.length);
                        }
                    }
                    next = item._children;
                    preItem = item;
                }
            }
        }
        if (preItem) {
            let child;
            if (preItem.disposed) {
                TreeNode.setGlobalTreeState(this.path, {
                    isLoadingPath: false,
                });
                return;
            }
            while ((child = flattenedBranchChilds.pop())) {
                child.expandBranch(child, true);
                if (flattenedBranchChilds.length === 0) {
                    this.updateTreeNodeCache(child);
                }
            }
            if (!quiet) {
                this.watcher.notifyDidUpdateBranch();
            }
            TreeNode.setGlobalTreeState(this.path, {
                isLoadingPath: false,
            });
            return preItem;
        }
        TreeNode.setGlobalTreeState(this.path, {
            isLoadingPath: false,
        });
    }
    /**
     * 根据节点获取节点ID下标位置
     * @param {number} id
     * @returns
     * @memberof CompositeTreeNode
     */
    getIndexAtTreeNodeId(id) {
        if (this._flattenedBranch) {
            return this._flattenedBranch.indexOf(id);
        }
        return -1;
    }
    /**
     * 根据节点获取节点下标位置
     * @param {ITreeNodeOrCompositeTreeNode} node
     * @returns
     * @memberof CompositeTreeNode
     */
    getIndexAtTreeNode(node) {
        if (this._flattenedBranch) {
            return this._flattenedBranch.indexOf(node.id);
        }
        return -1;
    }
    /**
     * 根据下标位置获取节点
     * @param {number} index
     * @returns
     * @memberof CompositeTreeNode
     */
    getTreeNodeAtIndex(index) {
        var _a;
        const id = (_a = this._flattenedBranch) === null || _a === void 0 ? void 0 : _a[index];
        if (!id) {
            return undefined;
        }
        return TreeNode.getTreeNodeById(id);
    }
    /**
     * 根据节点ID获取节点
     * @param {number} id
     * @returns
     * @memberof CompositeTreeNode
     */
    getTreeNodeById(id) {
        return TreeNode.getTreeNodeById(id);
    }
    /**
     * 根据节点路径获取节点
     * @param {string} path
     * @returns
     * @memberof CompositeTreeNode
     */
    getTreeNodeByPath(path) {
        return TreeNode.getTreeNodeByPath(path);
    }
}
exports.CompositeTreeNode = CompositeTreeNode;
CompositeTreeNode.REFRESH_DELAY = 200;
//# sourceMappingURL=TreeNode.js.map