"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExtensionServiceClientImpl = exports.DEFAULT_NLS_CONFIG_DIR = void 0;
const tslib_1 = require("tslib");
const os_1 = tslib_1.__importDefault(require("os"));
const path_1 = tslib_1.__importDefault(require("path"));
const di_1 = require("@opensumi/di");
const ide_connection_1 = require("@opensumi/ide-connection");
const hash_calculate_1 = require("@opensumi/ide-core-common/lib/hash-calculate/hash-calculate");
const ide_core_node_1 = require("@opensumi/ide-core-node");
const ide_file_service_1 = require("@opensumi/ide-file-service");
const common_1 = require("../common");
const lp = tslib_1.__importStar(require("./languagePack"));
exports.DEFAULT_NLS_CONFIG_DIR = path_1.default.join(os_1.default.homedir(), '.sumi');
let ExtensionServiceClientImpl = class ExtensionServiceClientImpl extends ide_connection_1.RPCService {
    constructor() {
        super(...arguments);
        this.languagePackCache = null;
    }
    setConnectionClientId(clientId) {
        this.clientId = clientId;
        this.extensionService.setConnectionServiceClient(this.clientId, this);
    }
    async getOpenVSXRegistry() {
        return this.appConfig.marketplace.endpoint;
    }
    async pid() {
        return this.extensionService.getExtProcessId(this.clientId);
    }
    infoProcessNotExist() {
        if (this.client) {
            return (0, ide_core_node_1.retry)(async () => {
                if (!this.client) {
                    throw new Error('Client not exist');
                }
                const pid = await this.pid();
                if (pid) {
                    this.logger.log('Process exist, clientId:', this.clientId, 'pid:', pid);
                    return true;
                }
                this.logger.log('Process not exist, try to restart, clientId:', this.clientId);
                const result = await this.client.$processNotExist(this.clientId);
                if (result === 'ok') {
                    this.logger.log('Process restart success, clientId:', this.clientId);
                    return true;
                }
                else {
                    throw new Error('Process not exist');
                }
            }, {
                delay: 1000,
                retries: 60 * 20,
                onFailedAttempt: (error) => {
                    this.logger.error('error when info browser that process not exists', error);
                },
            });
        }
    }
    restartExtProcessByClient() {
        if (this.client) {
            this.client.$restartExtProcess();
        }
    }
    infoProcessCrash() {
        if (this.client) {
            this.client.$processCrashRestart(this.clientId);
        }
    }
    async getElectronMainThreadListenPath(clientId) {
        return await this.extensionService.getElectronMainThreadListenPath(clientId);
    }
    /**
     * 创建插件进程
     *
     * @param clientId 客户端 id
     * @param options 创建插件参数
     */
    async createProcess(clientId, options) {
        await this.extensionService.createProcess(clientId, options);
        await this.extensionService.ensureProcessReady(clientId);
    }
    /**
     * 获取插件信息
     *
     * @param extensionPath 插件路径
     * @param extraMetaData 补充数据
     */
    async getExtension(extensionPath, localization, extraMetaData) {
        return await this.extensionService.getExtension(extensionPath, localization, extraMetaData);
    }
    /**
     * 获取所有插件
     *
     * @param scan 插件存放目录
     * @param extensionCandidate 执行插件目录
     * @param extraMetaData 扫描数据字段
     */
    async getAllExtensions(scan, extensionCandidate, localization, extraMetaData) {
        return await this.extensionService.getAllExtensions(scan, extensionCandidate, localization, extraMetaData);
    }
    async disposeClientExtProcess(clientId, info = true) {
        return await this.extensionService.disposeClientExtProcess(clientId, info);
    }
    /**
     * 将 packageJson 中声明的语言信息转换
     * @param packageJson package.json
     * @param languagePackPath language pack path
     */
    convertLanguagePack(packageJson, languagePackPath) {
        const { contributes: { localizations }, publisher, name, version, } = packageJson;
        const languagePacks = {};
        for (const localization of localizations) {
            // 这里需要添加languagePack路径作为id一部分，因为可能存在多个
            const id = `${languagePackPath}-${publisher.toLocaleLowerCase()}.${name.toLocaleLowerCase()}`;
            const _uuid = (0, ide_core_node_1.uuid)();
            const hash = this.hashCalculateService.calculate(id + (version !== null && version !== void 0 ? version : ''));
            languagePacks[localization.languageId] = {
                hash,
                extensions: [
                    {
                        version,
                        extensionIdentifier: {
                            id,
                            uuid: _uuid,
                        },
                    },
                ],
                translations: localization.translations.reduce((pre, translation) => {
                    pre[translation.id] = path_1.default.join(languagePackPath, translation.path);
                    return pre;
                }, {}),
            };
        }
        return languagePacks;
    }
    async setupNLSConfig(languageId, storagePath) {
        const nlsConfig = await lp.getNLSConfiguration(
        // This commit is used to generate the path for caching language packs.
        // In VSCode, it use its head ref commit. here we just use a fixed commit.
        'f06011ac164ae4dc8e753a3fe7f9549844d15e35', storagePath, languageId.toLowerCase());
        nlsConfig['_languagePackSupport'] = true;
        process.env.VSCODE_NLS_CONFIG = JSON.stringify(nlsConfig);
    }
    async updateLanguagePack(languageId, languagePack, storagePath) {
        var _a;
        let languagePacks = {};
        storagePath = storagePath || exports.DEFAULT_NLS_CONFIG_DIR;
        this.logger.log(`find ${languageId}， storagePath：${storagePath}`);
        const languagePath = ide_core_node_1.Uri.file(path_1.default.join(storagePath, 'languagepacks.json')).toString();
        if (await this.fileService.access(languagePath)) {
            const rawLanguagePacks = await this.fileService.resolveContent(languagePath);
            try {
                languagePacks = JSON.parse(rawLanguagePacks.content);
            }
            catch (err) {
                this.logger.error(err.message);
            }
        }
        else {
            await this.fileService.createFile(languagePath);
        }
        const rawPkgJson = (await this.fileService.resolveContent(ide_core_node_1.Uri.file(path_1.default.join(languagePack, 'package.json')).toString())).content;
        let packageJson;
        try {
            packageJson = JSON.parse(rawPkgJson);
        }
        catch (err) {
            this.logger.error(err.message);
        }
        if ((packageJson === null || packageJson === void 0 ? void 0 : packageJson.contributes) && ((_a = packageJson === null || packageJson === void 0 ? void 0 : packageJson.contributes) === null || _a === void 0 ? void 0 : _a.localizations)) {
            languagePacks = {
                ...languagePacks,
                ...this.convertLanguagePack(packageJson, languagePack),
            };
        }
        const languagePackJson = await this.fileService.getFileStat(languagePath);
        this.languagePackCache = languagePacks;
        await this.fileService.setContent(languagePackJson, JSON.stringify(languagePacks));
        await this.setupNLSConfig(languageId, storagePath);
    }
    getLanguagePack(languageId) {
        var _a;
        const languagePacks = (_a = this.languagePackCache) === null || _a === void 0 ? void 0 : _a[languageId];
        return Promise.resolve(languagePacks);
    }
};
exports.ExtensionServiceClientImpl = ExtensionServiceClientImpl;
tslib_1.__decorate([
    (0, di_1.Autowired)(common_1.IExtensionNodeService),
    tslib_1.__metadata("design:type", Object)
], ExtensionServiceClientImpl.prototype, "extensionService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_file_service_1.IFileService),
    tslib_1.__metadata("design:type", Object)
], ExtensionServiceClientImpl.prototype, "fileService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(hash_calculate_1.IHashCalculateService),
    tslib_1.__metadata("design:type", Object)
], ExtensionServiceClientImpl.prototype, "hashCalculateService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_node_1.AppConfig),
    tslib_1.__metadata("design:type", Object)
], ExtensionServiceClientImpl.prototype, "appConfig", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_node_1.INodeLogger),
    tslib_1.__metadata("design:type", Object)
], ExtensionServiceClientImpl.prototype, "logger", void 0);
tslib_1.__decorate([
    (0, ide_core_node_1.pMemoize)(),
    tslib_1.__metadata("design:type", Function),
    tslib_1.__metadata("design:paramtypes", []),
    tslib_1.__metadata("design:returntype", void 0)
], ExtensionServiceClientImpl.prototype, "infoProcessNotExist", null);
exports.ExtensionServiceClientImpl = ExtensionServiceClientImpl = tslib_1.__decorate([
    (0, di_1.Injectable)()
], ExtensionServiceClientImpl);
//# sourceMappingURL=extension.service.client.js.map