"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExtensionHostProxyManager = void 0;
const tslib_1 = require("tslib");
const net_1 = tslib_1.__importDefault(require("net"));
const di_1 = require("@opensumi/di");
const ide_connection_1 = require("@opensumi/ide-connection");
const connection_1 = require("@opensumi/ide-connection/lib/common/connection");
const ide_core_common_1 = require("@opensumi/ide-core-common");
const ide_core_node_1 = require("@opensumi/ide-core-node");
const common_1 = require("../common");
let ExtensionHostProxyManager = class ExtensionHostProxyManager {
    constructor(listenOptions = {
        port: common_1.EXT_HOST_PROXY_SERVER_PROT,
    }) {
        this.listenOptions = listenOptions;
        this.callId = 0;
        this.callbackMap = new Map();
        this.processDisposeMap = new Map();
        this.disposer = new ide_core_common_1.Disposable();
        this.LOG_TAG = '[ExtensionHostProxyManager]';
    }
    async init() {
        await this.startProxyServer();
    }
    startProxyServer() {
        return new Promise((resolve) => {
            const server = net_1.default.createServer();
            this.disposer.addDispose((0, ide_core_common_1.toDisposable)(() => {
                this.logger.warn(this.LOG_TAG, 'dispose server');
                server.close((err) => {
                    if (err) {
                        this.logger.error(this.LOG_TAG, 'close server error', err);
                    }
                });
            }));
            this.logger.log(this.LOG_TAG, 'waiting ext-proxy connecting...');
            server.on('connection', (socket) => {
                this.logger.log(this.LOG_TAG, 'there are new connections coming in');
                // 有新的连接时重新设置 RPCProtocol
                this.connection = new connection_1.NetSocketConnection(socket);
                this.disposer.addDispose((0, ide_core_common_1.toDisposable)(() => {
                    if (!socket.destroyed) {
                        socket.destroy();
                    }
                }));
                this.setExtHostProxyRPCProtocol();
                resolve();
            });
            server.listen(this.listenOptions);
        });
    }
    setExtHostProxyRPCProtocol() {
        this.extHostProxyProtocol = new ide_connection_1.SumiConnectionMultiplexer(this.connection, {
            timeout: this.appConfig.rpcMessageTimeout,
        });
        this.extHostProxyProtocol.set(common_1.EXT_SERVER_IDENTIFIER, {
            $callback: async (callId, ...args) => {
                const callback = this.callbackMap.get(callId);
                if (!callback) {
                    return Promise.reject(new Error(`no found callback: ${callId}`));
                }
                callback(...args);
            },
        });
        this.extHostProxy = this.extHostProxyProtocol.getProxy(common_1.EXT_HOST_PROXY_IDENTIFIER);
    }
    addNewCallback(pid, callback) {
        const callId = this.callId++;
        this.callbackMap.set(callId, callback);
        this.processDisposeMap.set(pid, (0, ide_core_common_1.toDisposable)(() => {
            this.callbackMap.delete(callId);
        }));
        this.disposer.addDispose((0, ide_core_common_1.toDisposable)(() => {
            this.processDisposeMap.delete(pid);
            this.callbackMap.delete(callId);
        }));
        return callId;
    }
    fork(modulePath, ...args) {
        return this.extHostProxy.$fork(modulePath, ...args);
    }
    send(pid, message) {
        return this.extHostProxy.$send(pid, message);
    }
    isRunning(pid) {
        return this.extHostProxy.$isRunning(pid);
    }
    treeKill(pid) {
        return this.extHostProxy.$treeKill(pid);
    }
    kill(pid, signal) {
        return this.extHostProxy.$kill(pid, signal);
    }
    isKilled(pid) {
        return this.extHostProxy.$isKilled(pid);
    }
    findDebugPort(startPort, giveUpAfter, timeout) {
        return this.extHostProxy.$findDebugPort(startPort, giveUpAfter, timeout);
    }
    onOutput(pid, listener) {
        const callId = this.addNewCallback(pid, listener);
        return this.extHostProxy.$onOutput(callId, pid);
    }
    onExit(pid, listener) {
        const callId = this.addNewCallback(pid, listener);
        return this.extHostProxy.$onExit(callId, pid);
    }
    onMessage(pid, listener) {
        const callId = this.addNewCallback(pid, listener);
        return this.extHostProxy.$onMessage(callId, pid);
    }
    disposeProcess(pid) {
        const disposer = this.processDisposeMap.get(pid);
        if (disposer) {
            disposer.dispose();
            this.processDisposeMap.delete(pid);
        }
        return this.extHostProxy.$disposeProcess(pid);
    }
    async dispose() {
        var _a;
        if (!this.disposer.disposed) {
            this.logger.log(this.LOG_TAG, 'dispose ext host proxy');
            await ((_a = this.extHostProxy) === null || _a === void 0 ? void 0 : _a.$dispose());
            this.disposer.dispose();
        }
    }
};
exports.ExtensionHostProxyManager = ExtensionHostProxyManager;
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_node_1.INodeLogger),
    tslib_1.__metadata("design:type", Object)
], ExtensionHostProxyManager.prototype, "logger", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_node_1.AppConfig),
    tslib_1.__metadata("design:type", Object)
], ExtensionHostProxyManager.prototype, "appConfig", void 0);
exports.ExtensionHostProxyManager = ExtensionHostProxyManager = tslib_1.__decorate([
    (0, di_1.Injectable)(),
    tslib_1.__param(0, (0, di_1.Optional)()),
    tslib_1.__metadata("design:paramtypes", [Object])
], ExtensionHostProxyManager);
//# sourceMappingURL=extension.host.proxy.manager.js.map