"use strict";
var ExtensionTreeViewModel_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExtensionTreeViewModel = exports.ITreeViewsService = exports.ITreeViewDragAndDropController = exports.ITreeViewBaseOptions = exports.ITreeViewId = exports.IExtensionTreeViewModel = void 0;
const tslib_1 = require("tslib");
const di_1 = require("@opensumi/di");
const ide_components_1 = require("@opensumi/ide-components");
const ide_core_browser_1 = require("@opensumi/ide-core-browser");
const next_1 = require("@opensumi/ide-core-browser/lib/menu/next");
const ide_core_common_1 = require("@opensumi/ide-core-common");
const vscode_1 = require("../../../../common/vscode");
const data_transfer_1 = require("../../../../common/vscode/data-transfer");
const main_thread_treeview_1 = require("../main.thread.treeview");
const tree_view_node_module_less_1 = tslib_1.__importDefault(require("./tree-view-node.module.less"));
const tree_view_model_1 = require("./tree-view.model");
const tree_view_node_defined_1 = require("./tree-view.node.defined");
exports.IExtensionTreeViewModel = Symbol('IExtensionTreeViewModel');
exports.ITreeViewId = Symbol('ITreeViewId');
exports.ITreeViewBaseOptions = Symbol('TreeViewBaseOptions');
exports.ITreeViewDragAndDropController = Symbol('ITreeViewDragAndDropController');
exports.ITreeViewsService = Symbol('ITreeViewsService');
const ITreeViewDataProvider = Symbol('ITreeViewDataProvider');
let ExtensionTreeViewModel = ExtensionTreeViewModel_1 = class ExtensionTreeViewModel {
    static createContainer(injector, tree, dndController, treeViewId, options) {
        const child = injector.createChild([
            {
                token: ITreeViewDataProvider,
                useValue: tree,
            },
            {
                token: exports.ITreeViewDragAndDropController,
                useValue: dndController,
            },
            {
                token: exports.IExtensionTreeViewModel,
                useClass: ExtensionTreeViewModel_1,
            },
            {
                token: exports.ITreeViewId,
                useValue: treeViewId,
            },
            {
                token: exports.ITreeViewBaseOptions,
                useValue: options,
            },
            {
                token: exports.ITreeViewsService,
                useValue: new vscode_1.TreeviewsService(),
            },
        ]);
        return child;
    }
    static createModel(injector, tree, dndController, treeViewId, options) {
        return ExtensionTreeViewModel_1.createContainer(injector, tree, dndController, treeViewId, options).get(exports.IExtensionTreeViewModel);
    }
    constructor() {
        // 装饰器
        this.selectedDecoration = new ide_components_1.Decoration(tree_view_node_module_less_1.default.mod_selected); // 选中态
        this.focusedDecoration = new ide_components_1.Decoration(tree_view_node_module_less_1.default.mod_focused); // 焦点态
        this.contextMenuDecoration = new ide_components_1.Decoration(tree_view_node_module_less_1.default.mod_actived); // 右键菜单激活态
        this.loadingDecoration = new ide_components_1.Decoration(tree_view_node_module_less_1.default.mod_loading); // 加载态
        this.draggingDecoration = new ide_components_1.Decoration(tree_view_node_module_less_1.default.mod_dragging); // Dragging 态
        this.draggedOverDecoration = new ide_components_1.Decoration(tree_view_node_module_less_1.default.mod_dragover); // Dragover 态
        // 开始拖拽的节点
        this.beingDraggedNodes = [];
        // 选中态的节点，会可能有多个
        this._selectedNodes = [];
        this.disposableCollection = new ide_core_browser_1.DisposableCollection();
        this.onDidFocusedNodeChangeEmitter = new ide_core_browser_1.Emitter();
        this.onDidSelectedNodeChangeEmitter = new ide_core_browser_1.Emitter();
        this.onDidChangeExpansionStateEmitter = new ide_core_browser_1.Emitter();
        this._isMultiSelected = false;
        this.revealDelayer = new ide_core_browser_1.ThrottledDelayer(ExtensionTreeViewModel_1.DEFAULT_REVEAL_DELAY);
        this.toCancelNodeExpansion = new ide_core_browser_1.DisposableCollection();
        this.dragOverTrigger = new ide_core_browser_1.ThrottledDelayer(ExtensionTreeViewModel_1.MS_TILL_DRAGGED_OVER_EXPANDS);
        this.treeItemsTransfer = data_transfer_1.LocalSelectionTransfer.getInstance();
        this.treeHandlerReadyDeffer = new ide_core_browser_1.Deferred();
        // 清空所有节点选中态
        this.clearNodeSelectedDecoration = () => {
            this._selectedNodes.forEach((node) => {
                this.selectedDecoration.removeTarget(node);
            });
            this._selectedNodes = [];
            this.onDidSelectedNodeChangeEmitter.fire([]);
        };
        // 清空其他选中/焦点态节点，更新当前焦点节点
        this.activeNodeDecoration = (target) => {
            if (target === this.treeModel.root) {
                // 根节点不能选中
                return;
            }
            if (this.contextMenuNode) {
                this.contextMenuDecoration.removeTarget(this.contextMenuNode);
                this._contextMenuNode = undefined;
            }
            if (target) {
                if (this.selectedNodes.length > 0) {
                    // 因为选择装饰器可能通过其他方式添加而不能及时在selectedNodes上更新
                    // 故这里遍历所有选中装饰器的节点进行一次统一清理
                    for (const target of this.selectedDecoration.appliedTargets.keys()) {
                        this.selectedDecoration.removeTarget(target);
                    }
                }
                if (this.focusedNode) {
                    this.focusedDecoration.removeTarget(this.focusedNode);
                }
                this.selectedDecoration.addTarget(target);
                this.focusedDecoration.addTarget(target);
                this._focusedNode = target;
                this._selectedNodes = [target];
                // 选中及焦点文件变化
                this.onDidFocusedNodeChangeEmitter.fire(target.treeItemId);
                this.onDidSelectedNodeChangeEmitter.fire([target.treeItemId]);
                // 通知视图更新
                this.treeModel.dispatchChange();
            }
        };
        // 清空其他焦点态节点，更新当前焦点节点，
        // removePreFocusedDecoration 表示更新焦点节点时如果此前已存在焦点节点，之前的节点装饰器将会被移除
        this.activeNodeFocusedDecoration = (target, removePreFocusedDecoration = false, clearSelection = false) => {
            if (target === this.treeModel.root) {
                // 根节点不能选中
                return;
            }
            if (this.focusedNode !== target) {
                if (removePreFocusedDecoration) {
                    if (this.focusedNode) {
                        // 多选情况下第一次切换焦点文件
                        this.focusedDecoration.removeTarget(this.focusedNode);
                    }
                    this._contextMenuNode = target;
                }
                else if (this.focusedNode) {
                    this._contextMenuNode = undefined;
                    this.focusedDecoration.removeTarget(this.focusedNode);
                }
                if (target) {
                    if (clearSelection) {
                        for (const node of this._selectedNodes) {
                            this.selectedDecoration.removeTarget(node);
                        }
                        this._selectedNodes = [];
                    }
                    if (this._selectedNodes.indexOf(target) < 0) {
                        this.selectedDecoration.addTarget(target);
                        this._selectedNodes.push(target);
                        // 事件通知选中状态变化
                        this.onDidSelectedNodeChangeEmitter.fire(this._selectedNodes.map((node) => node.treeItemId));
                    }
                    this.focusedDecoration.addTarget(target);
                    this._focusedNode = target;
                    // 事件通知焦点状态变化
                    this.onDidFocusedNodeChangeEmitter.fire(target.treeItemId);
                }
            }
            // 通知视图更新
            this.treeModel.dispatchChange();
        };
        // 右键菜单焦点态切换
        this.activeNodeActivedDecoration = (target) => {
            if (this.contextMenuNode) {
                this.contextMenuDecoration.removeTarget(this.contextMenuNode);
            }
            if (this.focusedNode) {
                this.focusedDecoration.removeTarget(this.focusedNode);
                this._focusedNode = undefined;
            }
            this.contextMenuDecoration.addTarget(target);
            this._contextMenuNode = target;
            this.treeModel.dispatchChange();
        };
        // 清空其他选中/焦点态节点，更新当前选中节点
        this.selectNodeDecoration = (target, dispatchChange = true) => {
            if (target === this.treeModel.root) {
                // 根节点不能选中
                return;
            }
            if (this.contextMenuNode) {
                this.contextMenuDecoration.removeTarget(this.contextMenuNode);
                this._contextMenuNode = undefined;
            }
            if (target) {
                if (this.selectedNodes.length > 0) {
                    this.selectedNodes.forEach((file) => {
                        this.selectedDecoration.removeTarget(file);
                    });
                }
                if (this.focusedNode) {
                    this.focusedDecoration.removeTarget(this.focusedNode);
                }
                this.selectedDecoration.addTarget(target);
                this._selectedNodes = [target];
                // 选中及焦点文件变化
                this.onDidSelectedNodeChangeEmitter.fire([target.treeItemId]);
                // 通知视图更新
                if (dispatchChange) {
                    this.treeModel.dispatchChange();
                }
            }
        };
        // 选中当前指定节点，添加装饰器属性
        this.activeNodeSelectedDecoration = (target) => {
            if (this._selectedNodes.indexOf(target) > -1) {
                return;
            }
            this._selectedNodes.push(target);
            this.selectedDecoration.addTarget(target);
            // 选中状态变化
            this.onDidSelectedNodeChangeEmitter.fire(this._selectedNodes.map((node) => node.treeItemId));
            // 通知视图更新
            this.treeModel.dispatchChange();
        };
        // 选中范围内的所有节点
        this.activeNodeDecorationByRange = (begin, end) => {
            this.clearNodeSelectedDecoration();
            this._contextMenuNode = undefined;
            for (; begin <= end; begin++) {
                const node = this.treeModel.root.getTreeNodeAtIndex(begin);
                if (node) {
                    this._selectedNodes.push(node);
                    this.selectedDecoration.addTarget(node);
                }
            }
            // 选中状态变化
            this.onDidSelectedNodeChangeEmitter.fire(this._selectedNodes.map((node) => node.treeItemId));
            // 通知视图更新
            this.treeModel.dispatchChange();
        };
        // 取消选中节点焦点
        this.enactiveNodeDecoration = () => {
            var _a;
            if (this.focusedNode) {
                this.focusedDecoration.removeTarget(this.focusedNode);
                this.onDidFocusedNodeChangeEmitter.fire();
                this._focusedNode = undefined;
            }
            if (this.contextMenuNode) {
                this.contextMenuDecoration.removeTarget(this.contextMenuNode);
            }
            (_a = this.treeModel) === null || _a === void 0 ? void 0 : _a.dispatchChange();
        };
        this.toggleDirectory = async (item) => {
            var _a, _b;
            await this.treeHandlerReadyDeffer.promise;
            if (item.expanded) {
                await ((_a = this.extensionTreeHandle) === null || _a === void 0 ? void 0 : _a.collapseNode(item));
            }
            else {
                await ((_b = this.extensionTreeHandle) === null || _b === void 0 ? void 0 : _b.expandNode(item));
            }
        };
        this.handleTreeBlur = () => {
            // 清空焦点状态
            this.enactiveNodeDecoration();
        };
        this.handleTreeFocus = () => {
            // 激活面板
        };
        this.handleDragStart = (event, node) => {
            event.stopPropagation();
            // React DragEnd Event maybe not fired for the last renderred element.
            // ref: https://stackoverflow.com/a/24543568
            const handleDragEnd = (ev) => {
                this.handleDragEnd(ev, node);
            };
            event.currentTarget.addEventListener('dragend', handleDragEnd, false);
            let draggedNodes = this.selectedNodes;
            let isDragWithSelectedNode = false;
            for (const selected of draggedNodes) {
                if (selected && selected.id === node.id) {
                    isDragWithSelectedNode = true;
                }
            }
            if (!isDragWithSelectedNode) {
                draggedNodes = [node];
            }
            const resources = [];
            const sourceInfo = {
                id: this.treeViewId,
                itemHandles: [],
            };
            draggedNodes.forEach((item) => {
                sourceInfo.itemHandles.push(item.treeItemId);
                if (item.uri) {
                    resources.push(ide_core_common_1.URI.revive(item.uri));
                }
            });
            this.addResourceInfoToTransfer(event, resources);
            this.addExtensionProvidedTransferTypes(event, sourceInfo.itemHandles);
            event.dataTransfer.setData(this.treeMimeType, JSON.stringify(sourceInfo));
            draggedNodes.forEach((node) => {
                // 添加拖拽样式
                this.draggingDecoration.addTarget(node, ide_components_1.TargetMatchMode.Self);
            });
            if (event.dataTransfer) {
                const label = this.getDragLabel(draggedNodes) || '';
                const dragImage = document.createElement('div');
                dragImage.className = tree_view_node_module_less_1.default.tree_view_drag_image;
                dragImage.textContent = label;
                document.body.appendChild(dragImage);
                event.dataTransfer.setDragImage(dragImage, -10, -10);
                setTimeout(() => document.body.removeChild(dragImage), 0);
            }
        };
        this.handleDragEnter = (event, _node) => {
            event.stopPropagation();
            event.preventDefault();
        };
        this.handleDrop = async (event, node) => {
            event.preventDefault();
            event.stopPropagation();
            event.dataTransfer.dropEffect = 'copy';
            if (node) {
                this.draggingDecoration.removeTarget(node);
            }
            if (this.potentialParent) {
                this.draggedOverDecoration.removeTarget(this.potentialParent);
            }
            // Remove all dragging decoration
            this.beingDraggedNodes.forEach((node) => {
                this.draggingDecoration.removeTarget(node);
            });
            this.beingDraggedNodes = [];
            this.potentialParent = null;
            this.treeModel.dispatchChange();
            if (!this.toCancelNodeExpansion.disposed) {
                this.toCancelNodeExpansion.dispose();
            }
            const dndController = this.treeViewDragAndDropController;
            if (!event.dataTransfer || !dndController) {
                return;
            }
            const originalDataTransfer = (0, data_transfer_1.toVSDataTransfer)(event.dataTransfer);
            let treeSourceInfo;
            let willDropUuid;
            if (this.treeItemsTransfer.hasData(data_transfer_1.DraggedTreeItemsIdentifier.prototype)) {
                willDropUuid = this.treeItemsTransfer.getData(data_transfer_1.DraggedTreeItemsIdentifier.prototype)[0].identifier;
            }
            // TODO: Handle Editor Drop Data
            const outDataTransfer = new data_transfer_1.VSDataTransfer();
            for (const [type, item] of originalDataTransfer.entries()) {
                if (type === this.treeMimeType ||
                    dndController.dropMimeTypes.includes(type) ||
                    (item.asFile() && dndController.dropMimeTypes.includes(data_transfer_1.DataTransfers.FILES.toLowerCase()))) {
                    outDataTransfer.append(type, item);
                    if (type === this.treeMimeType) {
                        try {
                            treeSourceInfo = JSON.parse(await item.asString());
                        }
                        catch (_a) {
                            // noop
                        }
                    }
                }
            }
            const additionalDataTransfer = await this.treeViewsDragAndDropService.removeDragOperationTransfer(willDropUuid);
            if (additionalDataTransfer) {
                for (const [type, item] of additionalDataTransfer.entries()) {
                    outDataTransfer.append(type, item);
                }
            }
            return dndController.handleDrop(outDataTransfer, node, ide_core_common_1.CancellationToken.None, willDropUuid, treeSourceInfo === null || treeSourceInfo === void 0 ? void 0 : treeSourceInfo.id, treeSourceInfo === null || treeSourceInfo === void 0 ? void 0 : treeSourceInfo.itemHandles);
        };
        this.handleDragOver = (event, node) => {
            event.preventDefault();
            event.stopPropagation();
            // TODO: Handle Editor Drop Data
            if (!this.toCancelNodeExpansion.disposed) {
                return;
            }
            if (this.beingDraggedNodes.indexOf(node) >= 0) {
                return;
            }
            this.draggedOverNode = node;
            const newPotentialParent = tree_view_node_defined_1.ExtensionCompositeTreeNode.is(node) && node.expanded
                ? node
                : node.parent;
            if (this.potentialParent !== newPotentialParent || !this.draggedOverDecoration.hasTarget(newPotentialParent)) {
                if (this.potentialParent) {
                    this.draggedOverDecoration.removeTarget(this.potentialParent);
                }
                this.potentialParent = newPotentialParent;
                this.draggedOverDecoration.addTarget(this.potentialParent, ide_components_1.TargetMatchMode.SelfAndChildren);
                // 通知视图更新
                this.treeModel.dispatchChange();
            }
            if (this.potentialParent !== node && tree_view_node_defined_1.ExtensionCompositeTreeNode.is(node)) {
                this.dragOverTrigger.trigger(async () => {
                    if (!node.expanded) {
                        await node.setExpanded(true);
                        // 确保当前仍在当前拖区域节点中
                        if (this.draggedOverNode === node) {
                            if (this.potentialParent) {
                                this.draggedOverDecoration.removeTarget(this.potentialParent);
                            }
                            this.potentialParent = node;
                            this.draggedOverDecoration.addTarget(this.potentialParent, ide_components_1.TargetMatchMode.SelfAndChildren);
                        }
                    }
                    else {
                        if (this.potentialParent) {
                            this.draggedOverDecoration.removeTarget(this.potentialParent);
                        }
                        this.potentialParent = node;
                        this.draggedOverDecoration.addTarget(this.potentialParent, ide_components_1.TargetMatchMode.SelfAndChildren);
                    }
                    // 通知视图更新
                    this.treeModel.dispatchChange();
                });
                this.toCancelNodeExpansion.push(ide_core_common_1.Disposable.create(() => {
                    if (!this.dragOverTrigger.isTriggered()) {
                        this.dragOverTrigger.cancel();
                    }
                }));
            }
        };
        this.handleDragLeave = (event, _node) => {
            event.preventDefault();
            event.stopPropagation();
            this.toCancelNodeExpansion.dispose();
            // Clear draggedOver decoration after leave
            if (this.potentialParent) {
                this.draggedOverDecoration.removeTarget(this.potentialParent);
                // Update view
                this.treeModel.dispatchChange();
            }
        };
        this.handleDragEnd = (event, node) => {
            var _a, _b;
            // Check if the drag was cancelled.
            if (((_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.dropEffect) === 'none') {
                (_b = this.dragCancellationToken) === null || _b === void 0 ? void 0 : _b.cancel();
            }
            this.draggingDecoration.removeTarget(node);
            if (this.potentialParent) {
                this.draggedOverDecoration.removeTarget(this.potentialParent);
            }
            this.beingDraggedNodes.forEach((node) => {
                // Remove dragging decoration
                this.draggingDecoration.removeTarget(node);
            });
            this.beingDraggedNodes = [];
            this.potentialParent = null;
            // Update view
            this.treeModel.dispatchChange();
            if (!this.toCancelNodeExpansion.disposed) {
                this.toCancelNodeExpansion.dispose();
            }
        };
        this.handleItemRangeClick = (item, type) => {
            if (!this.focusedNode) {
                this.handleItemClick(item, type);
            }
            else if (this.focusedNode && this.focusedNode !== item) {
                this._isMultiSelected = true;
                const targetIndex = this.treeModel.root.getIndexAtTreeNode(item);
                const preFocusedNodeIndex = this.treeModel.root.getIndexAtTreeNode(this.focusedNode);
                if (preFocusedNodeIndex > targetIndex) {
                    this.activeNodeDecorationByRange(targetIndex, preFocusedNodeIndex);
                }
                else if (preFocusedNodeIndex < targetIndex) {
                    this.activeNodeDecorationByRange(preFocusedNodeIndex, targetIndex);
                }
            }
        };
        this.handleItemToggleClick = (item, type) => {
            this._isMultiSelected = true;
            if (type !== ide_components_1.TreeNodeType.CompositeTreeNode && type !== ide_components_1.TreeNodeType.TreeNode) {
                return;
            }
            // 选中的节点不是选中状态时，默认先更新节点为选中状态
            // 后续点击切换焦点状态
            if (this.selectedNodes.indexOf(item) > -1) {
                if (this.focusedNode === item) {
                    this.enactiveNodeDecoration();
                }
                else {
                    this.activeNodeFocusedDecoration(item);
                }
            }
            else {
                this.activeNodeSelectedDecoration(item);
            }
        };
        this.handleItemClick = async (item, type) => {
            this._isMultiSelected = false;
            // 单选操作默认先更新选中状态
            if (type === ide_components_1.TreeNodeType.CompositeTreeNode || type === ide_components_1.TreeNodeType.TreeNode) {
                this.activeNodeDecoration(item);
            }
            if (!item.resolved) {
                await item.resolveTreeItem();
            }
            if (item.command) {
                this.commandService.executeCommand(item.command.id, ...(item.command.arguments || []));
            }
            else {
                this.clickTimes++;
                if (type === ide_components_1.TreeNodeType.CompositeTreeNode) {
                    if (this.preferenceService.get('workbench.list.openMode') === 'singleClick') {
                        this.toggleDirectory(item);
                    }
                }
                if (this.clickTimer) {
                    clearTimeout(this.clickTimer);
                }
                this.clickTimer = setTimeout(() => {
                    // 单击事件
                    // 200ms内多次点击默认为双击事件
                    if (this.clickTimes > 1) {
                        if (type !== ide_components_1.TreeNodeType.TreeNode) {
                            if (this.preferenceService.get('workbench.list.openMode') === 'doubleClick') {
                                this.toggleDirectory(item);
                            }
                        }
                    }
                    this.clickTimes = 0;
                }, 200);
            }
        };
        this.handleContextMenu = (ev, item) => {
            ev.stopPropagation();
            ev.preventDefault();
            const { x, y } = ev.nativeEvent;
            if (item) {
                this.activeNodeActivedDecoration(item);
            }
            else {
                this.enactiveNodeDecoration();
            }
            let nodes;
            let node;
            if (!item) {
                // 空白区域右键菜单
                nodes = [this.treeModel.root];
                node = this.treeModel.root;
            }
            else {
                node = item;
                if (this._isMultiSelected) {
                    if (this.selectedNodes.indexOf(node) >= 0) {
                        nodes = this._isMultiSelected ? this.selectedNodes : [node];
                    }
                    else {
                        nodes = this._isMultiSelected ? this.selectedNodes.concat([node]) : [node];
                    }
                }
                else {
                    nodes = [node];
                }
            }
            const menuNodes = this.getCtxMenuNodes(node.contextValue);
            const ctxMenuRenderer = this.injector.get(next_1.ICtxMenuRenderer);
            ctxMenuRenderer.show({
                anchor: { x, y },
                menuNodes,
                args: [
                    { treeViewId: this.treeViewId, treeItemId: node.treeItemId },
                    nodes.map((node) => ({ treeViewId: this.treeViewId, treeItemId: node.treeItemId })),
                ],
            });
        };
        this.handleCheckBoxChange = async (item) => {
            if (item) {
                this.treeViewDataProvider.markAsChecked(item, !item.checkboxInfo.checked, this.treeViewOptions.manageCheckboxStateManually);
            }
        };
        this._whenReady = this.initTreeModel();
        this.treeMimeType = `application/vnd.code.tree.${this.treeViewId.toLowerCase()}`;
    }
    get draggable() {
        return this.treeViewDragAndDropController.hasHandleDrag;
    }
    get onDidFocusedNodeChange() {
        return this.onDidFocusedNodeChangeEmitter.event;
    }
    get onDidChangeExpansionState() {
        return this.onDidChangeExpansionStateEmitter.event;
    }
    get onDidSelectedNodeChange() {
        return this.onDidSelectedNodeChangeEmitter.event;
    }
    get extensionTreeHandle() {
        return this._extensionTreeHandle;
    }
    get decorations() {
        return this._decorations;
    }
    get treeModel() {
        return this._treeModel;
    }
    get whenReady() {
        return this._whenReady;
    }
    // 既是选中态，也是焦点态节点
    get focusedNode() {
        return this._focusedNode;
    }
    // 是选中态，非焦点态节点
    get selectedNodes() {
        return this._selectedNodes;
    }
    // 右键菜单激活态节点
    get contextMenuNode() {
        return this._contextMenuNode;
    }
    async initTreeModel() {
        // 根据是否为多工作区创建不同根节点
        const root = (await this.treeViewDataProvider.resolveChildren())[0];
        this._treeModel = this.injector.get(tree_view_model_1.ExtensionTreeModel, [root]);
        this.initDecorations(root);
        this.disposableCollection.push(this.treeViewDataProvider);
        this.disposableCollection.push(this.treeModel.root.watcher.on(ide_components_1.TreeNodeEvent.WillResolveChildren, (target) => {
            this.loadingDecoration.addTarget(target);
        }));
        this.disposableCollection.push(this.treeModel.root.watcher.on(ide_components_1.TreeNodeEvent.DidResolveChildren, (target) => {
            this.loadingDecoration.removeTarget(target);
        }));
        this.disposableCollection.push(this.treeModel.root.watcher.on(ide_components_1.TreeNodeEvent.DidChangeExpansionState, (target, nowExpanded) => {
            this.onDidChangeExpansionStateEmitter.fire({
                treeItemId: target.treeItemId,
                expanded: nowExpanded,
            });
        }));
        this.disposableCollection.push(this.treeViewDataProvider.onTreeDataChanged((itemsToRefresh) => {
            this.refresh(itemsToRefresh);
        }));
        this.disposableCollection.push(this.treeViewDataProvider.onRevealChanged((treeItemId) => {
            this.reveal(treeItemId);
        }));
        this.disposableCollection.push(this.treeViewDataProvider.onRevealChanged((treeItemId) => {
            this.reveal(treeItemId);
        }));
    }
    async updateTreeModel() {
        const root = await this.treeViewDataProvider.resolveChildren()[0];
        this._treeModel = this.injector.get(tree_view_model_1.ExtensionTreeModel, [root]);
    }
    initDecorations(root) {
        this._decorations = new ide_components_1.DecorationsManager(root);
        this._decorations.addDecoration(this.selectedDecoration);
        this._decorations.addDecoration(this.focusedDecoration);
        this._decorations.addDecoration(this.contextMenuDecoration);
        this._decorations.addDecoration(this.loadingDecoration);
        this._decorations.addDecoration(this.draggedOverDecoration);
        this._decorations.addDecoration(this.draggingDecoration);
    }
    removeNodeDecoration() {
        if (!this.decorations) {
            return;
        }
        this.decorations.removeDecoration(this.selectedDecoration);
        this.decorations.removeDecoration(this.focusedDecoration);
        this.decorations.removeDecoration(this.contextMenuDecoration);
        this.decorations.removeDecoration(this.loadingDecoration);
        this.decorations.removeDecoration(this.draggedOverDecoration);
        this.decorations.removeDecoration(this.draggingDecoration);
    }
    handleTreeHandler(handle) {
        this._extensionTreeHandle = handle;
        this.treeHandlerReadyDeffer.resolve();
    }
    getDragURI(element) {
        if (!this.treeViewDragAndDropController.handleDrag) {
            return null;
        }
        return element.uri ? ide_core_common_1.Uri.revive(element.uri).toString() : element.treeItemId;
    }
    getDragLabel(elements) {
        if (!this.treeViewDragAndDropController.handleDrag) {
            return undefined;
        }
        if (elements.length > 1) {
            return String(elements.length);
        }
        const element = elements[0];
        return element.displayName
            ? element.displayName
            : element.uri
                ? this.labelService.getName(ide_core_common_1.URI.from(element.uri))
                : undefined;
    }
    handleDragAndLog(dndController, itemHandles, uuid, dragCancellationToken) {
        return dndController.handleDrag(itemHandles, uuid, dragCancellationToken).then((additionalDataTransfer) => {
            if (additionalDataTransfer) {
                const unlistedTypes = [];
                for (const item of additionalDataTransfer.entries()) {
                    if (item[0] !== this.treeMimeType &&
                        dndController.dragMimeTypes.findIndex((value) => value === item[0]) < 0) {
                        unlistedTypes.push(item[0]);
                    }
                }
                if (unlistedTypes.length) {
                    this.logger.warn(`Drag and drop controller for tree ${this.treeViewId} adds the following data transfer types but does not declare them in dragMimeTypes: ${unlistedTypes.join(', ')}`);
                }
            }
            return additionalDataTransfer;
        });
    }
    addExtensionProvidedTransferTypes(event, itemHandles) {
        var _a;
        if (!event.dataTransfer || !this.treeViewDragAndDropController) {
            return;
        }
        const uid = (0, ide_core_common_1.uuid)();
        this.dragCancellationToken = new ide_core_common_1.CancellationTokenSource();
        this.treeViewsDragAndDropService.addDragOperationTransfer(uid, this.handleDragAndLog(this.treeViewDragAndDropController, itemHandles, uid, this.dragCancellationToken.token));
        this.treeItemsTransfer.setData([new data_transfer_1.DraggedTreeItemsIdentifier(uid)], data_transfer_1.DraggedTreeItemsIdentifier.prototype);
        if (this.treeViewDragAndDropController.dragMimeTypes.find((element) => element === ide_core_common_1.Mimes.uriList)) {
            // Add the type that the editor knows
            (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.setData(data_transfer_1.DataTransfers.RESOURCES, '');
        }
        this.treeViewDragAndDropController.dragMimeTypes.forEach((supportedType) => {
            var _a;
            (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.setData(supportedType, '');
        });
    }
    addResourceInfoToTransfer(event, resources) {
        if (resources.length && event.dataTransfer) {
            // TODO: Apply some datatransfer types to allow for dragging the element outside of the application
            // The only custom data transfer we set from the explorer is a file transfer
            // to be able to DND between multiple code file explorers across windows
            const fileResources = resources.filter((s) => s.scheme === ide_core_common_1.Schemes.file).map((r) => r.fsPath);
            if (fileResources.length) {
                event.dataTransfer.setData(data_transfer_1.CodeDataTransfers.FILES, JSON.stringify(fileResources));
            }
        }
    }
    getCtxMenuNodes(viewItemValue) {
        return this.getMenuNodes(viewItemValue)[1];
    }
    getMenuNodes(viewItemValue) {
        const viewContextKey = this.contextKeyService.createScoped();
        viewContextKey.createKey('view', this.treeViewId);
        viewContextKey.createKey('viewItem', viewItemValue);
        // viewItem
        const menus = this.menuService.createMenu(next_1.MenuId.ViewItemContext, viewContextKey);
        const result = (0, next_1.generateCtxMenu)({ menus, separator: 'inline' });
        menus.dispose();
        viewContextKey.dispose();
        return result;
    }
    getInlineMenuNodes(viewItemValue) {
        return this.getMenuNodes(viewItemValue)[0];
    }
    collapseAll() {
        this.treeModel.root.collapsedAll();
    }
    async refreshById(treeItemId) {
        const id = this.treeViewDataProvider.getTreeNodeIdByTreeItemId(treeItemId);
        if (!id) {
            return;
        }
        const treeNode = this.treeModel.root.getTreeNodeById(id);
        if (!treeNode) {
            return;
        }
        if (tree_view_node_defined_1.ExtensionCompositeTreeNode.is(treeNode)) {
            await treeNode.refresh();
        }
        else if (treeNode.parent) {
            await treeNode.parent.refresh();
        }
    }
    async refresh(item) {
        var _a;
        await this.whenReady;
        if (!item) {
            await ((_a = this.treeModel.root) === null || _a === void 0 ? void 0 : _a.refresh());
        }
        else {
            await this.refreshById(item.id);
        }
    }
    async reveal(treeItemId, options = {}) {
        await this.whenReady;
        if (!this.revealDelayer.isTriggered()) {
            this.revealDelayer.cancel();
        }
        return this.revealDelayer.trigger(async () => {
            var _a;
            await this.treeHandlerReadyDeffer.promise;
            if (this.treeModel.root.branchSize === 0) {
                // 当Tree为空时，刷新一次Tree
                await this.refresh();
            }
            const id = this.treeViewDataProvider.getTreeNodeIdByTreeItemId(treeItemId);
            if (!id) {
                return;
            }
            const cache = this.treeModel.root.getTreeNodeById(id);
            if (!cache) {
                return;
            }
            const select = (0, ide_core_common_1.isUndefinedOrNull)(options.select) ? false : options.select;
            const focus = (0, ide_core_common_1.isUndefinedOrNull)(options.focus) ? false : options.focus;
            // 递归展开几层节点，最多三层
            let expand = Math.min((0, ide_core_common_1.isNumber)(options.expand) ? options.expand : options.expand === true ? 1 : 0, 3);
            let itemsToExpand = await ((_a = this.extensionTreeHandle) === null || _a === void 0 ? void 0 : _a.ensureVisible(cache.path));
            if (itemsToExpand) {
                if (select) {
                    // 更新节点选中态，不会改变焦点态节点
                    this.selectNodeDecoration(itemsToExpand);
                }
                if (focus) {
                    // 给节点焦点样式并更新当前选中态
                    this.activeNodeFocusedDecoration(itemsToExpand, false, true);
                }
            }
            for (; tree_view_node_defined_1.ExtensionCompositeTreeNode.is(itemsToExpand) && expand > 0; expand--) {
                await this.extensionTreeHandle.expandNode(itemsToExpand);
                itemsToExpand = (itemsToExpand === null || itemsToExpand === void 0 ? void 0 : itemsToExpand.children) ? itemsToExpand === null || itemsToExpand === void 0 ? void 0 : itemsToExpand.children[0] : undefined;
            }
        });
    }
};
exports.ExtensionTreeViewModel = ExtensionTreeViewModel;
ExtensionTreeViewModel.DEFAULT_REVEAL_DELAY = 500;
ExtensionTreeViewModel.MS_TILL_DRAGGED_OVER_EXPANDS = 500;
tslib_1.__decorate([
    (0, di_1.Autowired)(di_1.INJECTOR_TOKEN),
    tslib_1.__metadata("design:type", di_1.Injector)
], ExtensionTreeViewModel.prototype, "injector", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ITreeViewDataProvider),
    tslib_1.__metadata("design:type", main_thread_treeview_1.TreeViewDataProvider)
], ExtensionTreeViewModel.prototype, "treeViewDataProvider", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(exports.ITreeViewDragAndDropController),
    tslib_1.__metadata("design:type", main_thread_treeview_1.TreeViewDragAndDropController)
], ExtensionTreeViewModel.prototype, "treeViewDragAndDropController", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_browser_1.PreferenceService),
    tslib_1.__metadata("design:type", Object)
], ExtensionTreeViewModel.prototype, "preferenceService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(exports.ITreeViewId),
    tslib_1.__metadata("design:type", String)
], ExtensionTreeViewModel.prototype, "treeViewId", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(exports.ITreeViewBaseOptions),
    tslib_1.__metadata("design:type", Object)
], ExtensionTreeViewModel.prototype, "treeViewOptions", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(next_1.AbstractMenuService),
    tslib_1.__metadata("design:type", next_1.AbstractMenuService)
], ExtensionTreeViewModel.prototype, "menuService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_browser_1.IContextKeyService),
    tslib_1.__metadata("design:type", Object)
], ExtensionTreeViewModel.prototype, "contextKeyService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_browser_1.CommandService),
    tslib_1.__metadata("design:type", Object)
], ExtensionTreeViewModel.prototype, "commandService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_browser_1.LabelService),
    tslib_1.__metadata("design:type", ide_core_browser_1.LabelService)
], ExtensionTreeViewModel.prototype, "labelService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_common_1.ILogger),
    tslib_1.__metadata("design:type", Object)
], ExtensionTreeViewModel.prototype, "logger", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(exports.ITreeViewsService),
    tslib_1.__metadata("design:type", Object)
], ExtensionTreeViewModel.prototype, "treeViewsDragAndDropService", void 0);
exports.ExtensionTreeViewModel = ExtensionTreeViewModel = ExtensionTreeViewModel_1 = tslib_1.__decorate([
    (0, di_1.Injectable)(),
    tslib_1.__metadata("design:paramtypes", [])
], ExtensionTreeViewModel);
//# sourceMappingURL=tree-view.model.service.js.map