"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExtensionDebugService = void 0;
const tslib_1 = require("tslib");
const di_1 = require("@opensumi/di");
const ide_core_browser_1 = require("@opensumi/ide-core-browser");
const ide_debug_1 = require("@opensumi/ide-debug");
const debug_configuration_manager_1 = require("@opensumi/ide-debug/lib/browser/debug-configuration-manager");
const ide_workspace_1 = require("@opensumi/ide-workspace");
const ext_types_1 = require("../../../../common/vscode/ext-types");
const types_1 = require("../../../types");
let ExtensionDebugService = class ExtensionDebugService {
    constructor() {
        this.contributors = new Map();
        this.toDispose = new ide_core_browser_1.DisposableCollection();
        // sessionID到贡献点Map
        this.sessionId2contrib = new Map();
        this.activationEvents = new Set();
        this.init();
    }
    init() {
        this.debugSessionManager.onWillStartDebugSession((event) => this.ensureDebugActivation(event));
        this.debugSessionManager.onWillResolveDebugConfiguration((event) => this.ensureDebugActivation(event, 'onDebugResolve', event.debugType));
        this.debugConfigurationManager.onWillProvideDebugConfiguration((event) => this.ensureDebugActivation(event, 'onDebugInitialConfigurations'));
        this.toDispose.pushAll([
            ide_core_browser_1.Disposable.create(() => {
                for (const sessionId of this.sessionId2contrib.keys()) {
                    const contrib = this.sessionId2contrib.get(sessionId);
                    contrib.terminateDebugSession(sessionId);
                }
                this.sessionId2contrib.clear();
            }),
        ]);
    }
    registerDebugAdapterContribution(contrib) {
        const { type } = contrib;
        if (this.contributors.has(type)) {
            this.logger.warn(`Debugger with type '${type}' already registered.`);
            return ide_core_browser_1.Disposable.NULL;
        }
        this.contributors.set(type, contrib);
        return ide_core_browser_1.Disposable.create(() => this.unregisterDebugAdapterContribution(type));
    }
    unregisterDebugAdapterContribution(debugType) {
        this.contributors.delete(debugType);
    }
    ensureDebugActivation(event, activationEvent, debugType) {
        if (typeof event.waitUntil === 'function') {
            event.waitUntil(this.activateByDebug(activationEvent, debugType));
        }
    }
    async activateByDebug(activationEvent, debugType) {
        const promises = [this.activationEventService.fireEvent('onDebug')];
        if (activationEvent) {
            promises.push(this.activationEventService.fireEvent(activationEvent));
            if (debugType) {
                promises.push(this.activationEventService.fireEvent(activationEvent, debugType));
            }
        }
        await Promise.all(promises);
    }
    async debugTypes() {
        return Array.from(this.contributors.keys());
    }
    async provideDebugConfigurations(debugType, workspaceFolderUri, triggerKind) {
        const contributor = this.contributors.get(debugType);
        if (contributor) {
            return ((contributor.provideDebugConfigurations &&
                contributor.provideDebugConfigurations(workspaceFolderUri, undefined, triggerKind)) ||
                []);
        }
        else {
            return [];
        }
    }
    // 获取 DebugConfigurationProviderTriggerKind.Dynamic 类型的调试配置支持类型和 Label
    async getDynamicConfigurationsSupportTypes() {
        const dynamicSupportedTypes = new Set();
        // 通过解析插件的 Contributes 获取 debuggers 的 type，避开激活插件的过程，避免资源损耗
        this.extInstanceManagementService.getExtensionInstances().forEach((ext) => {
            var _a, _b;
            const extManifest = ext.packageJSON;
            const onDebugDynamicConfigurationsName = 'onDebugDynamicConfigurations';
            if (!extManifest.activationEvents) {
                return;
            }
            const explicitTypes = [];
            let hasGenericEvent = false;
            for (const event of extManifest.activationEvents) {
                if (event === onDebugDynamicConfigurationsName) {
                    hasGenericEvent = true;
                }
                else if (event.startsWith(`${onDebugDynamicConfigurationsName}:`)) {
                    explicitTypes.push(event.slice(onDebugDynamicConfigurationsName.length + 1));
                }
            }
            if (explicitTypes.length) {
                explicitTypes.forEach((t) => dynamicSupportedTypes.add(t));
            }
            else if (hasGenericEvent) {
                // VSCode 的目前也只取了 debuggers 的第一个的 type，后面需要支持多个的话再改
                // 参考的 Commit 记录：https://github.com/microsoft/vscode/commit/3a9d44e8c38c277c56ded331e13c1e033b7ffef4
                const debuggerType = (_b = (_a = extManifest.contributes) === null || _a === void 0 ? void 0 : _a.debuggers) === null || _b === void 0 ? void 0 : _b[0].type;
                if (debuggerType) {
                    dynamicSupportedTypes.add(debuggerType);
                }
            }
        });
        // 根据已经注册的 Providers 获取，用于弥补某种动态注册 Provider 未被识别的情况
        for (const [type, contribution] of this.contributors) {
            const count = await contribution.getDebugConfigurationProvidersCount(ext_types_1.DebugConfigurationProviderTriggerKind.Dynamic);
            if (count > 0) {
                dynamicSupportedTypes.add(type);
            }
        }
        return Array.from(dynamicSupportedTypes);
    }
    async resolveDebugConfiguration(config, workspaceFolderUri) {
        const contributor = this.contributors.get(config.type);
        if (contributor) {
            try {
                const next = await contributor.resolveDebugConfiguration(config, workspaceFolderUri);
                return next;
            }
            catch (e) {
                this.logger.error(e);
            }
        }
    }
    async resolveDebugConfigurationWithSubstitutedVariables(config, workspaceFolderUri) {
        const contributor = this.contributors.get(config.type);
        if (contributor) {
            try {
                const next = await contributor.resolveDebugConfigurationWithSubstitutedVariables(config, workspaceFolderUri);
                return next;
            }
            catch (e) {
                this.logger.error(e);
            }
        }
    }
    async getDebuggersForLanguage(language) {
        const debuggers = [];
        for (const contributor of this.contributors.values()) {
            const languages = await contributor.languages;
            if (languages && languages.indexOf(language) !== -1) {
                const { type } = contributor;
                debuggers.push({ type, label: (await contributor.label) || type });
            }
        }
        return debuggers;
    }
    async getSchemaAttributes(debugType) {
        const contributor = this.contributors.get(debugType);
        if (contributor) {
            return (contributor.getSchemaAttributes && contributor.getSchemaAttributes()) || [];
        }
        else {
            return [];
        }
    }
    async getConfigurationSnippets() {
        let snippets = [];
        for (const contributor of this.contributors.values()) {
            if (contributor.getConfigurationSnippets) {
                snippets = snippets.concat(await contributor.getConfigurationSnippets());
            }
        }
        return snippets;
    }
    async createDebugSession(dto) {
        const { configuration } = dto;
        const contributor = this.contributors.get(configuration.type);
        if (contributor) {
            const sessionId = await contributor.createDebugSession(dto);
            this.sessionId2contrib.set(sessionId, contributor);
            return sessionId;
        }
    }
    async terminateDebugSession(sessionId) {
        const contributor = this.sessionId2contrib.get(sessionId);
        if (contributor) {
            this.sessionId2contrib.delete(sessionId);
            return contributor.terminateDebugSession(sessionId);
        }
    }
    dispose() {
        this.toDispose.dispose();
    }
};
exports.ExtensionDebugService = ExtensionDebugService;
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_workspace_1.IWorkspaceService),
    tslib_1.__metadata("design:type", Object)
], ExtensionDebugService.prototype, "workspaceService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_browser_1.ILogger),
    tslib_1.__metadata("design:type", Object)
], ExtensionDebugService.prototype, "logger", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_debug_1.IDebugSessionManager),
    tslib_1.__metadata("design:type", Object)
], ExtensionDebugService.prototype, "debugSessionManager", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(debug_configuration_manager_1.DebugConfigurationManager),
    tslib_1.__metadata("design:type", debug_configuration_manager_1.DebugConfigurationManager)
], ExtensionDebugService.prototype, "debugConfigurationManager", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(types_1.IActivationEventService),
    tslib_1.__metadata("design:type", types_1.IActivationEventService)
], ExtensionDebugService.prototype, "activationEventService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(types_1.AbstractExtInstanceManagementService),
    tslib_1.__metadata("design:type", types_1.AbstractExtInstanceManagementService)
], ExtensionDebugService.prototype, "extInstanceManagementService", void 0);
exports.ExtensionDebugService = ExtensionDebugService = tslib_1.__decorate([
    (0, di_1.Injectable)(),
    tslib_1.__metadata("design:paramtypes", [])
], ExtensionDebugService);
//# sourceMappingURL=extension-debug-service.js.map