"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MainThreadTerminal = void 0;
const tslib_1 = require("tslib");
const di_1 = require("@opensumi/di");
const ide_connection_1 = require("@opensumi/ide-connection");
const ide_core_browser_1 = require("@opensumi/ide-core-browser");
const ide_terminal_next_1 = require("@opensumi/ide-terminal-next");
const environmentVariable_1 = require("@opensumi/ide-terminal-next/lib/common/environmentVariable");
const profile_1 = require("@opensumi/ide-terminal-next/lib/common/profile");
const vscode_1 = require("../../../common/vscode");
const types_1 = require("../../types");
let MainThreadTerminal = class MainThreadTerminal {
    constructor(rpcProtocol) {
        this.rpcProtocol = rpcProtocol;
        this.shortId2LongIdMap = new Map();
        this._terminalProcessProxies = new Map();
        this._profileProviders = new Map();
        this.disposable = new ide_core_browser_1.Disposable();
        this.proxy = this.rpcProtocol.getProxy(vscode_1.ExtHostAPIIdentifier.ExtHostTerminal);
        this.initData();
        this.bindEvent();
    }
    dispose() {
        this.disposable.dispose();
    }
    bindEvent() {
        this.disposable.addDispose(this.terminalApi.onDidChangeActiveTerminal((id) => {
            this.proxy.$onDidChangeActiveTerminal(id);
        }));
        this.disposable.addDispose(this.terminalApi.onDidCloseTerminal((e) => {
            this.proxy.$onDidCloseTerminal(e);
        }));
        this.disposable.addDispose(this.terminalApi.onDidTerminalTitleChange((e) => {
            this.proxy.$onDidTerminalTitleChange(e.id, e.name);
        }));
        this.disposable.addDispose(this.terminalApi.onDidOpenTerminal((info) => {
            const client = this.controller.clients.get(info.id);
            if (client) {
                client.addDispose(client.xterm.raw.onData(() => {
                    this.proxy.$acceptTerminalInteraction(info.id);
                }));
            }
            this.proxy.$onDidOpenTerminal(info);
        }));
        this.disposable.addDispose(this.controller.onInstanceRequestStartExtensionTerminal((e) => this._onRequestStartExtensionTerminal(e)));
        this.disposable.addDispose(this.profileService.onDidChangeAvailableProfiles(() => {
            this._updateDefaultProfile();
        }));
        this.disposable.addDispose(this.profileService.onTerminalProfileResolved(async (id) => {
            await this.activationEventService.fireEvent(`onTerminalProfile:${id}`);
        }));
        this.disposable.addDispose(this.profileService.onDidChangeDefaultShell((shell) => {
            this.proxy.$setShell(shell);
        }));
    }
    initData() {
        const terminals = this.terminalApi.terminals;
        const infoList = [];
        terminals.forEach((term) => {
            infoList.push({
                id: term.id,
                name: term.name,
                isActive: term.isActive,
            });
        });
        this.proxy.$setTerminals(infoList);
        this._updateDefaultProfile();
    }
    transform(id, cb) {
        const sessionId = this.shortId2LongIdMap.get(id);
        return cb(sessionId || id);
    }
    $sendText(id, text, addNewLine) {
        return this.transform(id, (sessionId) => {
            this.proxy.$acceptTerminalInteraction(sessionId);
            return this.terminalApi.sendText(sessionId, text, addNewLine);
        });
    }
    $show(id, preserveFocus) {
        return this.transform(id, (sessionId) => this.terminalApi.showTerm(sessionId, preserveFocus));
    }
    $hide(id) {
        return this.transform(id, (sessionId) => this.terminalApi.hideTerm(sessionId));
    }
    $dispose(id) {
        return this.transform(id, (sessionId) => this.terminalApi.removeTerm(sessionId));
    }
    $getProcessId(id) {
        return this.transform(id, (sessionId) => this.terminalApi.getProcessId(sessionId));
    }
    async $createTerminal(options, shortId) {
        await this.controller.ready.promise;
        const terminal = await this.terminalApi.createTerminal(options, shortId);
        if (!terminal) {
            // 应该要 throw Error
            this.logger.error(`Create Terminal ${shortId} fail.`);
            return;
        }
        this.shortId2LongIdMap.set(shortId, terminal.id);
    }
    _onRequestStartExtensionTerminal(request) {
        const proxy = request.proxy;
        this._terminalProcessProxies.set(proxy.terminalId, proxy);
        // Note that onResize is not being listened to here as it needs to fire when max dimensions
        // change, excluding the dimension override
        const initialDimensions = request.cols && request.rows
            ? {
                columns: request.cols,
                rows: request.rows,
            }
            : undefined;
        this.proxy.$startExtensionTerminal(proxy.terminalId, initialDimensions).then(request.callback);
        proxy.onInput((data) => this.proxy.$acceptProcessInput(proxy.terminalId, data));
        proxy.onShutdown((immediate) => this.proxy.$acceptProcessShutdown(proxy.terminalId, immediate));
        proxy.onRequestCwd(() => this.proxy.$acceptProcessRequestCwd(proxy.terminalId));
        proxy.onRequestInitialCwd(() => this.proxy.$acceptProcessRequestInitialCwd(proxy.terminalId));
    }
    _getTerminalProcess(id) {
        return this.transform(id, (terminalId) => {
            const terminal = this._terminalProcessProxies.get(terminalId);
            if (!terminal) {
                throw new Error(`Unknown terminal: ${terminalId}`);
            }
            return terminal;
        });
    }
    $sendProcessTitle(id, title) {
        return this.transform(id, (terminalId) => {
            const terminalWidgetInstance = this.terminalGroupViewService.getWidget(terminalId);
            if (terminalWidgetInstance) {
                terminalWidgetInstance.rename(title);
                this.proxy.$acceptTerminalTitleChange(terminalId, title);
            }
        });
    }
    $sendProcessData(terminalId, data) {
        this._getTerminalProcess(terminalId).emitData(data);
    }
    $sendProcessReady(terminalId, pid, cwd) {
        this._getTerminalProcess(terminalId).emitReady(pid, cwd);
    }
    $sendProcessExit(terminalId, exitCode) {
        this._getTerminalProcess(terminalId).emitExit(exitCode);
        this._terminalProcessProxies.delete(terminalId);
    }
    $sendOverrideDimensions(terminalId, dimensions) {
        this._getTerminalProcess(terminalId).emitOverrideDimensions(dimensions);
    }
    $sendProcessInitialCwd(terminalId, initialCwd) {
        this._getTerminalProcess(terminalId).emitInitialCwd(initialCwd);
    }
    $sendProcessCwd(terminalId, cwd) {
        this._getTerminalProcess(terminalId).emitCwd(cwd);
    }
    $startLinkProvider() {
        var _a;
        (_a = this._linkProvider) === null || _a === void 0 ? void 0 : _a.dispose();
        this._linkProvider = this.controller.registerLinkProvider(new ExtensionTerminalLinkProvider(this.proxy));
    }
    $stopLinkProvider() {
        var _a;
        (_a = this._linkProvider) === null || _a === void 0 ? void 0 : _a.dispose();
        this._linkProvider = undefined;
    }
    $registerProfileProvider(id, extensionIdentifier) {
        // Proxy profile provider requests through the extension host
        this._profileProviders.set(id, this.profileService.registerTerminalProfileProvider(extensionIdentifier, id, {
            createContributedTerminalProfile: async (options) => {
                this.proxy.$createContributedProfileTerminal(id, options);
            },
        }));
    }
    $unregisterProfileProvider(id) {
        var _a;
        (_a = this._profileProviders.get(id)) === null || _a === void 0 ? void 0 : _a.dispose();
        this._profileProviders.delete(id);
    }
    async _updateDefaultProfile() {
        const defaultProfile = await this.profileInternalSerivce.resolveDefaultProfile();
        if (defaultProfile) {
            this.proxy.$acceptDefaultProfile(defaultProfile);
        }
    }
    $setEnvironmentVariableCollection(extensionIdentifier, persistent, collection) {
        if (collection) {
            const translatedCollection = {
                persistent,
                map: (0, environmentVariable_1.deserializeEnvironmentVariableCollection)(collection),
            };
            this.environmentVariableService.set(extensionIdentifier, translatedCollection);
        }
        else {
            this.environmentVariableService.delete(extensionIdentifier);
        }
    }
};
exports.MainThreadTerminal = MainThreadTerminal;
tslib_1.__decorate([
    (0, di_1.Autowired)(environmentVariable_1.EnvironmentVariableServiceToken),
    tslib_1.__metadata("design:type", Object)
], MainThreadTerminal.prototype, "environmentVariableService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_terminal_next_1.ITerminalApiService),
    tslib_1.__metadata("design:type", Object)
], MainThreadTerminal.prototype, "terminalApi", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_terminal_next_1.ITerminalController),
    tslib_1.__metadata("design:type", Object)
], MainThreadTerminal.prototype, "controller", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(profile_1.ITerminalProfileService),
    tslib_1.__metadata("design:type", Object)
], MainThreadTerminal.prototype, "profileService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_terminal_next_1.ITerminalProfileInternalService),
    tslib_1.__metadata("design:type", Object)
], MainThreadTerminal.prototype, "profileInternalSerivce", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_terminal_next_1.ITerminalGroupViewService),
    tslib_1.__metadata("design:type", Object)
], MainThreadTerminal.prototype, "terminalGroupViewService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_browser_1.PreferenceService),
    tslib_1.__metadata("design:type", Object)
], MainThreadTerminal.prototype, "preference", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(types_1.IActivationEventService),
    tslib_1.__metadata("design:type", types_1.IActivationEventService)
], MainThreadTerminal.prototype, "activationEventService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_browser_1.ILogger),
    tslib_1.__metadata("design:type", Object)
], MainThreadTerminal.prototype, "logger", void 0);
exports.MainThreadTerminal = MainThreadTerminal = tslib_1.__decorate([
    (0, di_1.Injectable)({ multiple: true }),
    tslib_1.__param(0, (0, di_1.Optional)(ide_connection_1.IRPCProtocol)),
    tslib_1.__metadata("design:paramtypes", [Object])
], MainThreadTerminal);
class ExtensionTerminalLinkProvider {
    constructor(_proxy) {
        this._proxy = _proxy;
    }
    async provideLinks(instance, line) {
        const proxy = this._proxy;
        const extHostLinks = await proxy.$provideLinks(instance.id, line);
        return extHostLinks.map((dto) => ({
            id: dto.id,
            startIndex: dto.startIndex,
            length: dto.length,
            label: dto.label,
            activate: () => proxy.$activateLink(instance.id, dto.id),
        }));
    }
}
//# sourceMappingURL=main.thread.terminal.js.map