"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NodeExtProcessService = void 0;
const tslib_1 = require("tslib");
const di_1 = require("@opensumi/di");
const ide_connection_1 = require("@opensumi/ide-connection");
const browser_1 = require("@opensumi/ide-connection/lib/browser");
const ide_core_browser_1 = require("@opensumi/ide-core-browser");
const common_1 = require("../common");
const main_thread_extender_1 = require("../common/main.thread.extender");
const vscode_1 = require("../common/vscode");
const protocols_1 = require("../common/vscode/protocols");
const main_thread_api_impl_1 = require("./sumi/main.thread.api.impl");
const main_thread_api_impl_2 = require("./vscode/api/main.thread.api.impl");
const main_thread_api_shared_impl_1 = require("./vscode/api/main.thread.api.shared-impl");
let NodeExtProcessService = class NodeExtProcessService {
    constructor() {
        this._apiFactoryDisposables = new ide_core_browser_1.DisposableStore();
        this.ready = new ide_core_browser_1.Deferred();
        this._extHostUpdated = new ide_core_browser_1.Deferred();
        this.extensions = [];
    }
    disposeApiFactory() {
        this._apiFactoryDisposables.clear();
    }
    async disposeProcess() {
        this.disposeApiFactory();
        await this.extensionNodeClient.disposeClientExtProcess(this.clientId, false);
    }
    async activate() {
        await this.createExtProcess();
        if (this.protocol) {
            this.ready.resolve();
            await this.createBrowserMainThreadAPI();
            const proxy = await this.getProxy();
            await proxy.$updateExtHostData();
            this._extHostUpdated.resolve();
        }
        return this.protocol;
    }
    async activeExtension(extension, isWebExtension) {
        if (!this.appConfig.noExtHost && !isWebExtension) {
            // 只有当 proxy.$updateExtHostData 调用之后才可以开始激活插件
            await this._extHostUpdated.promise;
            const proxy = await this.getProxy();
            await proxy.$activateExtension(extension.id);
        }
    }
    async updateExtensionData(extensions) {
        this.extensions = extensions;
        if (this.protocol) {
            const proxy = await this.getProxy();
            // 同步 host 进程中的 extension 列表
            await proxy.$updateExtHostData();
            // 发送 extension 变化
            proxy.$fireChangeEvent();
        }
    }
    getExtension(extensionId) {
        return this.extensions.find((n) => n.id === extensionId);
    }
    // 以下两者是给插件进程调用的 rpc call
    async $activateExtension(extensionPath) {
        const extension = this.extensions.find((n) => n.path === extensionPath);
        if (extension) {
            await extension.activate();
        }
    }
    async $getExtensions() {
        return this.extensions.map((n) => n.toJSON());
    }
    async getProxy() {
        await this.ready.promise;
        return this.protocol.getProxy(vscode_1.ExtHostAPIIdentifier.ExtHostExtensionService);
    }
    async createBrowserMainThreadAPI() {
        const apiProxy = (0, main_thread_api_shared_impl_1.initSharedAPIProxy)(this.protocol, this.injector);
        this._apiFactoryDisposables.add(apiProxy);
        this._apiFactoryDisposables.add((0, ide_core_browser_1.toDisposable)((0, main_thread_api_impl_2.initNodeThreadAPIProxy)(this.protocol, this.injector, this)));
        this._apiFactoryDisposables.add((0, ide_core_browser_1.toDisposable)((0, main_thread_api_impl_1.createSumiAPIFactory)(this.protocol, this.injector)));
        this._apiFactoryDisposables.add(this.createExternalSumiAPIFactory());
        await apiProxy.setup();
    }
    getSpawnOptions() {
        return {};
    }
    /**
     * register external main thread class
     * @returns disposer
     */
    createExternalSumiAPIFactory() {
        const disposer = new ide_core_browser_1.Disposable();
        // register main thread extender contribution
        const contributions = this.mainThreadExtenderContributionProvider.getContributions();
        for (const contribution of contributions) {
            contribution.registerMainThreadExtender(this.mainThreadExtenderService);
        }
        // instantiate this MainThreadExtenderClass
        const extenders = this.mainThreadExtenderService.getMainThreadExtenders();
        for (const extender of extenders) {
            const service = this.injector.get(extender.serviceClass, [this.protocol]);
            this.protocol.set(extender.identifier, service);
            disposer.addDispose(service);
        }
        return disposer;
    }
    async getActivatedExtensions() {
        const proxy = await this.getProxy();
        return await proxy.$getActivatedExtensions();
    }
    get clientId() {
        return this.applicationService.clientId;
    }
    async createExtProcess() {
        await this.extensionNodeClient.createProcess(this.clientId, {
            enableDebugExtensionHost: this.appConfig.enableDebugExtensionHost,
            inspectExtensionHost: this.appConfig.inspectExtensionHost,
            extensionConnectOption: this.appConfig.extensionConnectOption,
            extHostSpawnOptions: this.getSpawnOptions(),
        });
        await this.initExtProtocol();
    }
    /**
     * 这个 protocol 需要每次都重新创建，因为服务端是会在该 channel 连上后才开始进行插件进程相关的逻辑的
     */
    async initExtProtocol() {
        var _a, _b;
        if (this.channel) {
            this.channel.dispose();
        }
        if (this.protocol) {
            (_b = (_a = this.protocol).dispose) === null || _b === void 0 ? void 0 : _b.call(_a);
        }
        this.channel = await this.channelHandler.openChannel(common_1.CONNECTION_HANDLE_BETWEEN_EXTENSION_AND_MAIN_THREAD);
        this.connection = this.channel.createConnection();
        this.protocol = new ide_connection_1.SumiConnectionMultiplexer(this.connection, {
            timeout: this.appConfig.rpcMessageTimeout,
            name: 'node-ext-host',
            io: (0, ide_connection_1.createExtMessageIO)(protocols_1.knownProtocols),
        });
    }
};
exports.NodeExtProcessService = NodeExtProcessService;
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_browser_1.AppConfig),
    tslib_1.__metadata("design:type", Object)
], NodeExtProcessService.prototype, "appConfig", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(di_1.INJECTOR_TOKEN),
    tslib_1.__metadata("design:type", di_1.Injector)
], NodeExtProcessService.prototype, "injector", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(common_1.ExtensionNodeServiceServerPath),
    tslib_1.__metadata("design:type", Object)
], NodeExtProcessService.prototype, "extensionNodeClient", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_browser_1.IApplicationService),
    tslib_1.__metadata("design:type", Object)
], NodeExtProcessService.prototype, "applicationService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(browser_1.WSChannelHandler),
    tslib_1.__metadata("design:type", browser_1.WSChannelHandler)
], NodeExtProcessService.prototype, "channelHandler", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(main_thread_extender_1.IMainThreadExtenderService),
    tslib_1.__metadata("design:type", Object)
], NodeExtProcessService.prototype, "mainThreadExtenderService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(main_thread_extender_1.MainThreadExtenderContribution),
    tslib_1.__metadata("design:type", Object)
], NodeExtProcessService.prototype, "mainThreadExtenderContributionProvider", void 0);
exports.NodeExtProcessService = NodeExtProcessService = tslib_1.__decorate([
    (0, di_1.Injectable)()
], NodeExtProcessService);
//# sourceMappingURL=extension-node.service.js.map