"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MainThreadEditorTabsService = void 0;
const tslib_1 = require("tslib");
const di_1 = require("@opensumi/di");
const ide_connection_1 = require("@opensumi/ide-connection");
const merge_editor_widget_1 = require("@opensumi/ide-core-browser/lib/monaco/merge-editor-widget");
const ide_core_common_1 = require("@opensumi/ide-core-common");
const ide_editor_1 = require("@opensumi/ide-editor");
const workbench_editor_service_1 = require("@opensumi/ide-editor/lib/browser/workbench-editor.service");
const index_1 = require("./../../../common/vscode/index");
let MainThreadEditorTabsService = class MainThreadEditorTabsService extends ide_core_common_1.Disposable {
    constructor(rpcProtocol) {
        super();
        this.rpcProtocol = rpcProtocol;
        this.prevEditorGroups = new Set();
        this.groupDataStore = new Map();
        this.tabStore = new EditorTabDtoDataStore();
        this.proxy = this.rpcProtocol.getProxy(index_1.ExtHostAPIIdentifier.ExtHostEditorTabs);
        this.addDispose(this.workbenchEditorService.onDidEditorGroupsChanged(() => {
            this.updateGroups();
        }));
        this.addDispose(this.workbenchEditorService.onActiveResourceChange(() => {
            this.updateGroups();
        }));
        this.workbenchEditorService.contributionsReady.promise.then(() => {
            this.updateGroups();
        });
    }
    $initializeState() {
        this.updateGroups();
    }
    $moveTab(tabId, index, viewColumn, preserveFocus) {
        const target = this.findEditorTabData(tabId);
        if (target) {
            const { group, resource } = target;
            let targetEditorGroup = group;
            if (!(0, ide_core_common_1.isUndefined)(viewColumn)) {
                targetEditorGroup = this.workbenchEditorService.sortedEditorGroups[viewColumn];
            }
            if (targetEditorGroup) {
                targetEditorGroup.dropUri(resource.uri, ide_editor_1.DragOverPosition.CENTER, group, targetEditorGroup.resources[index]);
            }
            else {
                group.dropUri(resource.uri, ide_editor_1.DragOverPosition.RIGHT);
            }
        }
    }
    async $closeTab(tabIds, preserveFocus) {
        const res = await Promise.all(tabIds.map(async (tabId) => {
            const target = this.findEditorTabData(tabId);
            if (target) {
                return await target.group.close(target.resource.uri);
            }
        }));
        return res.filter((r) => !!r).length > 0;
    }
    async $closeGroup(groupIds, preservceFocus) {
        const res = await Promise.all(groupIds.map(async (g) => {
            var _a;
            const editorGroup = (_a = this.groupDataStore.get(g)) === null || _a === void 0 ? void 0 : _a.editorGroup;
            if (editorGroup) {
                try {
                    return await editorGroup.closeAll();
                }
                catch (e) {
                    return false;
                }
            }
        }));
        return res.filter((r) => !!r).length > 0;
    }
    findEditorTabData(tabId) {
        return this.tabStore.all.get(tabId);
    }
    getOrCreateGroupData(group) {
        if (!this.groupDataStore.has(group.groupId)) {
            const data = new EditorTabGroupData(group, this.workbenchEditorService, this.tabStore, this.proxy);
            data.addDispose({
                dispose: () => {
                    if (this.groupDataStore.get(group.groupId) === data) {
                        this.groupDataStore.delete(group.groupId);
                    }
                },
            });
            this.groupDataStore.set(group.groupId, data);
        }
        return this.groupDataStore.get(group.groupId);
    }
    updateGroups() {
        const diff = (0, ide_core_common_1.diffSets)(this.prevEditorGroups, new Set(this.workbenchEditorService.editorGroups));
        if (diff.added.length > 0 || diff.removed.length > 0) {
            // 做一次完整更新
            this.proxy.$acceptEditorTabModel(this.workbenchEditorService.editorGroups.map((group) => {
                const data = this.getOrCreateGroupData(group);
                return {
                    ...data.dto,
                    tabs: data.tabs.map((t) => t.dto),
                };
            }));
        }
        else {
            this.workbenchEditorService.editorGroups.forEach((group) => {
                const data = this.getOrCreateGroupData(group);
                data.tryCheckUpdate();
            });
        }
        this.prevEditorGroups = new Set(this.workbenchEditorService.editorGroups);
    }
};
exports.MainThreadEditorTabsService = MainThreadEditorTabsService;
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_editor_1.WorkbenchEditorService),
    tslib_1.__metadata("design:type", workbench_editor_service_1.WorkbenchEditorServiceImpl)
], MainThreadEditorTabsService.prototype, "workbenchEditorService", void 0);
exports.MainThreadEditorTabsService = MainThreadEditorTabsService = tslib_1.__decorate([
    (0, di_1.Injectable)({ multiple: true }),
    tslib_1.__param(0, (0, di_1.Optional)(Symbol())),
    tslib_1.__metadata("design:paramtypes", [Object])
], MainThreadEditorTabsService);
class EditorTabDtoData {
    constructor(group, resource) {
        this.group = group;
        this.resource = resource;
        this.tryUpdate();
    }
    updateResource(resource) {
        this.resource = resource;
    }
    /**
     * @param updateDto
     */
    tryUpdate() {
        const updateDto = EditorTabDtoData.from(this.group, this.resource);
        if (this._dto && JSON.stringify(this._dto) !== JSON.stringify(updateDto)) {
            this._dto = updateDto;
            return true;
        }
        else {
            this._dto = updateDto;
            return false;
        }
    }
    get dto() {
        return this._dto;
    }
    static getTabId(editorGroup, resource) {
        return `${editorGroup.groupId}~${resource.uri.toString()}`;
    }
    get index() {
        return this.group.resources.indexOf(this.resource);
    }
    static from(editorGroup, resource) {
        var _a, _b, _c, _d, _e, _f;
        const tabId = EditorTabDtoData.getTabId(editorGroup, resource);
        const openType = editorGroup.getLastOpenType(resource);
        let input = {
            kind: 0 /* TabInputKind.UnknownInput */,
        };
        if (openType) {
            if (openType.type === 'code') {
                input = {
                    kind: 1 /* TabInputKind.TextInput */,
                    uri: resource.uri.codeUri,
                };
            }
            else if (openType.type === 'diff') {
                const { metadata } = resource;
                if (metadata) {
                    input = {
                        kind: 2 /* TabInputKind.TextDiffInput */,
                        original: metadata.original.codeUri,
                        modified: metadata.modified.codeUri,
                    };
                }
            }
            else if (openType.type === 'mergeEditor') {
                const { metadata } = resource;
                if (metadata) {
                    const { ancestor, input1, input2, output } = metadata;
                    const input1Data = merge_editor_widget_1.MergeEditorInputData.from(input1);
                    const input2Data = merge_editor_widget_1.MergeEditorInputData.from(input2);
                    input = {
                        kind: 3 /* TabInputKind.TextMergeInput */,
                        base: ide_core_common_1.Uri.parse(ancestor),
                        input1: input1Data.uri.codeUri,
                        input2: input2Data.uri.codeUri,
                        result: ide_core_common_1.Uri.parse(output),
                    };
                }
            }
            else if (openType.type === 'component') {
                // 区分 webview / customEditor
                const component = editorGroup.editorComponentRegistry.getEditorComponent(openType.componentId);
                if ((_a = component === null || component === void 0 ? void 0 : component.metadata) === null || _a === void 0 ? void 0 : _a.extWebview) {
                    input = {
                        kind: 7 /* TabInputKind.WebviewEditorInput */,
                        viewType: (_b = component === null || component === void 0 ? void 0 : component.metadata) === null || _b === void 0 ? void 0 : _b.extWebview,
                    };
                }
                else if ((_c = component === null || component === void 0 ? void 0 : component.metadata) === null || _c === void 0 ? void 0 : _c.customEditor) {
                    input = {
                        kind: 6 /* TabInputKind.CustomEditorInput */,
                        viewType: (_d = component === null || component === void 0 ? void 0 : component.metadata) === null || _d === void 0 ? void 0 : _d.customEditor,
                        uri: resource.uri.codeUri,
                    };
                }
            }
        }
        return {
            id: tabId,
            label: resource.name,
            input,
            isActive: editorGroup.currentResource === resource,
            isPinned: false, // 暂时还没这个功能,
            isPreview: !!((_e = editorGroup.previewURI) === null || _e === void 0 ? void 0 : _e.isEqual(resource.uri)),
            isDirty: !!((_f = editorGroup.resourceService.getResourceDecoration(resource.uri)) === null || _f === void 0 ? void 0 : _f.dirty),
        };
    }
}
class EditorTabDtoDataStore {
    constructor() {
        this.all = new Map();
        this.mapByUri = new Map();
    }
    getOrCreateData(group, resource) {
        const tabId = EditorTabDtoData.getTabId(group, resource);
        if (!this.all.has(tabId)) {
            const data = new EditorTabDtoData(group, resource);
            const uriString = resource.uri.toString();
            if (!this.mapByUri.has(uriString)) {
                this.mapByUri.set(uriString, new Map());
            }
            this.mapByUri.get(uriString).set(tabId, data);
            this.all.set(tabId, data);
        }
        else {
            this.all.get(tabId).updateResource(resource);
        }
        return this.all.get(tabId);
    }
    removeData(id) {
        var _a, _b;
        const data = this.all.get(id);
        if (data) {
            this.all.delete(id);
            const uriString = data.resource.uri.toString();
            (_a = this.mapByUri.get(uriString)) === null || _a === void 0 ? void 0 : _a.delete(id);
            if (((_b = this.mapByUri.get(uriString)) === null || _b === void 0 ? void 0 : _b.size) === 0) {
                this.mapByUri.delete(uriString);
            }
        }
    }
    getByResourceUri(uri) {
        var _a;
        return Array.from(((_a = this.mapByUri.get(uri.toString())) === null || _a === void 0 ? void 0 : _a.values()) || []);
    }
}
class EditorTabGroupData extends ide_core_common_1.Disposable {
    constructor(editorGroup, editorService, store, proxy) {
        super();
        this.editorGroup = editorGroup;
        this.editorService = editorService;
        this.store = store;
        this.proxy = proxy;
        this.tabs = [];
        this._data = undefined;
        this.editorGroup.addDispose(this);
        this.init();
    }
    init() {
        this.tabs = this.editorGroup.resources.map((r) => this.store.getOrCreateData(this.editorGroup, r));
        this.addDispose(this.editorGroup.onDidEditorGroupTabOperation((operation) => {
            const kind = {
                open: 0 /* TabModelOperationKind.TAB_OPEN */,
                close: 1 /* TabModelOperationKind.TAB_CLOSE */,
                move: 3 /* TabModelOperationKind.TAB_MOVE */,
            }[operation.type];
            const tabDtoData = this.store.getOrCreateData(this.editorGroup, operation.resource);
            tabDtoData.tryUpdate();
            this.proxy.$acceptTabOperation({
                kind,
                groupId: this.editorGroup.groupId,
                tabDto: tabDtoData.dto,
                index: operation.index,
                oldIndex: operation.oldIndex,
            });
        }));
        this.addDispose(this.editorGroup.onDidEditorGroupBodyChanged(() => {
            this.onTabsMayUpdated();
        }));
        this.addDispose(this.editorGroup.onDidEditorGroupTabChanged(() => {
            this.onTabsMayUpdated();
        }));
    }
    onTabsMayUpdated() {
        this.tabs = this.editorGroup.resources.map((r, index) => {
            const data = this.store.getOrCreateData(this.editorGroup, r);
            const isChanged = data.tryUpdate();
            if (isChanged) {
                this.proxy.$acceptTabOperation({
                    kind: 2 /* TabModelOperationKind.TAB_UPDATE */,
                    tabDto: data.dto,
                    index,
                    groupId: this.editorGroup.groupId,
                });
            }
            return data;
        });
    }
    tryCheckUpdate() {
        const oldData = this._data;
        const newData = {
            groupId: this.editorGroup.groupId,
            isActive: this.editorService.currentEditorGroup === this.editorGroup,
            viewColumn: this.editorGroup.index,
        };
        this._data = newData;
        if (oldData) {
            if (oldData.viewColumn !== newData.viewColumn) {
                // changed
                this.proxy.$acceptTabGroupUpdate({
                    ...this.dto,
                    tabs: [], // update 事件中不会真正消费 tabs
                });
            }
            else if (!oldData.isActive && newData.isActive) {
                // 只有原来不是 active ，新的是 active 才要发 （和 vscode 行为对齐）
                this.proxy.$acceptTabGroupUpdate({
                    ...this.dto,
                    tabs: [], // update 事件中不会真正消费 tabs
                });
            }
        }
    }
    get dto() {
        if (!this._data) {
            this._data = {
                groupId: this.editorGroup.groupId,
                isActive: this.editorService.currentEditorGroup === this.editorGroup,
                viewColumn: this.editorGroup.index,
            };
        }
        return this._data;
    }
}
//# sourceMappingURL=main.thread.editor-tabs.js.map