"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CompletionEventsType = exports.KT_APP_CONFIG_KEY = exports.KT_PROCESS_PRELOAD_KEY = exports.KT_PROCESS_SOCK_OPTION_KEY = exports.IExtensionHostManager = exports.OutputType = exports.ExtensionHostProfilerServiceToken = exports.ExtensionHostProfilerServicePath = exports.ExtensionHostKind = exports.EMIT_EXT_HOST_EVENT = exports.EXTENSION_ENABLE = exports.ProcessMessageType = exports.WorkerHostAPIIdentifier = exports.MOCK_EXTENSION_EXTEND_PROXY_IDENTIFIER = exports.EXTENSION_EXTEND_SERVICE_PREFIX = exports.LIFE_CYCLE_PHASE_KEY = exports.CONTRIBUTE_NAME_KEY = exports.ExtensionContributesService = exports.VSCodeContributePoint = exports.NO_ROOT_URI = exports.LANGUAGE_BUNDLE_FIELD = exports.ExtensionCapabilityRegistry = exports.ExtensionService = exports.ERestartPolicy = exports.AbstractExtensionManagementService = exports.IExtCommandManagement = exports.IExtensionNodeClientService = exports.IExtensionNodeService = exports.ExtensionNodeServiceServerPath = void 0;
exports.Contributes = Contributes;
exports.LifeCycle = LifeCycle;
exports.getExtensionId = getExtensionId;
exports.validateTypeOrModifier = validateTypeOrModifier;
const tslib_1 = require("tslib");
const di_1 = require("@opensumi/di");
const ide_connection_1 = require("@opensumi/ide-connection");
const ide_core_common_1 = require("@opensumi/ide-core-common");
const semantic_tokens_registry_1 = require("@opensumi/ide-theme/lib/common/semantic-tokens-registry");
const theme_service_1 = require("@opensumi/ide-theme/lib/common/theme.service");
exports.ExtensionNodeServiceServerPath = 'ExtensionNodeServiceServerPath';
exports.IExtensionNodeService = Symbol('IExtensionNodeService');
exports.IExtensionNodeClientService = Symbol('IExtensionNodeClientService');
/**
 * 管理不同进程内插件注册的 command 的运行环境及其调用
 */
class IExtCommandManagement {
}
exports.IExtCommandManagement = IExtCommandManagement;
/**
 * 为插件市场面板提供数据/交互
 */
class AbstractExtensionManagementService {
}
exports.AbstractExtensionManagementService = AbstractExtensionManagementService;
var ERestartPolicy;
(function (ERestartPolicy) {
    /**
     * Always restart extension process
     */
    ERestartPolicy["Always"] = "always";
    /**
     * Restart extension process when extension process is not running or not responding
     */
    ERestartPolicy["WhenExit"] = "when-exit";
})(ERestartPolicy || (exports.ERestartPolicy = ERestartPolicy = {}));
class ExtensionService {
}
exports.ExtensionService = ExtensionService;
class ExtensionCapabilityRegistry {
}
exports.ExtensionCapabilityRegistry = ExtensionCapabilityRegistry;
exports.LANGUAGE_BUNDLE_FIELD = 'languageBundle';
exports.NO_ROOT_URI = '<none>';
const VAR_REGEXP = /^\$\(([a-z.]+\/)?([a-z-]+)(~[a-z]+)?\)$/i;
class VSCodeContributePoint extends ide_core_common_1.Disposable {
    constructor() {
        super(...arguments);
        this.contributesMap = [];
        this.contributedMap = [];
    }
    register(extensionId, contributes) {
        this.contributesMap.push({ extensionId, contributes });
    }
    hasUncontributedPoint() {
        return this.contributesMap.length > 0;
    }
    afterContribute() {
        this.contributedMap = this.contributedMap.concat(this.contributesMap);
        this.contributesMap = [];
    }
    toIconClass(iconContrib, type = theme_service_1.IconType.Mask, basePath) {
        var _a, _b;
        if (typeof iconContrib === 'string' && VAR_REGEXP.test(iconContrib)) {
            return (_a = this.iconService) === null || _a === void 0 ? void 0 : _a.fromString(iconContrib);
        }
        return (_b = this.iconService) === null || _b === void 0 ? void 0 : _b.fromIcon(basePath, iconContrib, type);
    }
    getLocalizeFromNlsJSON(title, extensionId, languageId) {
        return (0, ide_core_common_1.replaceNlsField)(title, extensionId, title, languageId);
    }
    createLocalizedStr(title, extensionId) {
        return (0, ide_core_common_1.createLocalizedStr)(title, extensionId, title, undefined, 'default');
    }
}
exports.VSCodeContributePoint = VSCodeContributePoint;
class ExtensionContributesService extends ide_core_common_1.WithEventBus {
    constructor() {
        super(...arguments);
        this.contributedSet = new Set();
        this.contributeQueue = new ide_core_common_1.Throttler();
        this.lifecycles = [];
    }
    getContributionCls(contributesName) {
        const Constructor = this.ContributionPoints.find((Constructor) => {
            const k = Reflect.getMetadata(exports.CONTRIBUTE_NAME_KEY, Constructor);
            if (k === contributesName) {
                return true;
            }
            return false;
        });
        return Constructor;
    }
    register(extensionId, contrib) {
        for (const k of Object.keys(contrib)) {
            const Constructor = this.getContributionCls(k);
            if (Constructor) {
                const instance = this.injector.get(Constructor);
                instance === null || instance === void 0 ? void 0 : instance.register(extensionId, contrib[k]);
            }
        }
    }
    async runContributesByPhase(lifeCyclePhase) {
        const Contributes = this.ContributionPoints.filter((Constructor) => {
            const phase = Reflect.getMetadata(exports.LIFE_CYCLE_PHASE_KEY, Constructor);
            const contributeName = Reflect.getMetadata(exports.CONTRIBUTE_NAME_KEY, Constructor);
            if (phase <= lifeCyclePhase && !this.contributedSet.has(contributeName)) {
                this.contributedSet.add(contributeName);
                return true;
            }
            return false;
        });
        await Promise.all(Contributes.map(async (Constructor) => {
            try {
                const contributePoint = this.injector.get(Constructor);
                const contributeName = Reflect.getMetadata(exports.CONTRIBUTE_NAME_KEY, Constructor);
                this.addDispose(contributePoint);
                if (contributePoint.hasUncontributedPoint()) {
                    const now = Date.now();
                    await contributePoint.contribute();
                    contributePoint.afterContribute();
                    this.extensionsSchemaService.registerExtensionPoint({
                        extensionPoint: contributeName,
                        jsonSchema: Constructor.schema || {},
                        frameworkKind: ['vscode', 'opensumi'],
                    });
                    const end = Date.now() - now;
                    this.logger.log(`run extension contribute ${contributeName}: ${end} ms`);
                }
            }
            catch (e) {
                this.logger.error(e);
            }
        }));
    }
    initialize() {
        return new Promise((resolve) => {
            const doRunContributes = async () => {
                const phases = this.lifecycles.slice(0);
                this.lifecycles = [];
                if (phases.length === 0) {
                    return;
                }
                for (const phase of phases) {
                    // 所有 contributionPoint 运行完后清空
                    // 确保后续安装/启用插件后可以正常激活
                    if (phase === 4 /* LifeCyclePhase.Ready */) {
                        this.contributedSet.clear();
                    }
                    await this.runContributesByPhase(phase);
                    if (phase === 2 /* LifeCyclePhase.Initialize */) {
                        // 返回 Promise，说明此时初始化已完成
                        resolve();
                    }
                }
            };
            const runContributes = async (phase = this.lifecycleService.phase) => {
                this.lifecycles.push(phase);
                this.contributeQueue.queue(doRunContributes);
            };
            this.addDispose(this.lifecycleService.onDidLifeCyclePhaseChange((newPhase) => {
                runContributes(newPhase);
            }));
            // 由于渲染上是异步调用，故 Browser 层可能比 Node 层更快的执行到后续生命周期
            // 同时，重启流程触发时也需要完整执行所有生命周期贡献点
            if (this.lifecycleService.phase === 4 /* LifeCyclePhase.Ready */) {
                runContributes(2 /* LifeCyclePhase.Initialize */);
                runContributes(3 /* LifeCyclePhase.Starting */);
                runContributes(4 /* LifeCyclePhase.Ready */);
            }
            else if (this.lifecycleService.phase === 3 /* LifeCyclePhase.Starting */) {
                runContributes(2 /* LifeCyclePhase.Initialize */);
                runContributes(3 /* LifeCyclePhase.Starting */);
            }
            else {
                runContributes();
            }
        });
    }
}
exports.ExtensionContributesService = ExtensionContributesService;
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_common_1.ILogger),
    tslib_1.__metadata("design:type", Object)
], ExtensionContributesService.prototype, "logger", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_common_1.AppLifeCycleServiceToken),
    tslib_1.__metadata("design:type", Object)
], ExtensionContributesService.prototype, "lifecycleService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_common_1.IExtensionsSchemaService),
    tslib_1.__metadata("design:type", Object)
], ExtensionContributesService.prototype, "extensionsSchemaService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(di_1.INJECTOR_TOKEN),
    tslib_1.__metadata("design:type", di_1.Injector)
], ExtensionContributesService.prototype, "injector", void 0);
exports.CONTRIBUTE_NAME_KEY = 'contribute_name';
function Contributes(name) {
    return (target) => {
        Reflect.defineMetadata(exports.CONTRIBUTE_NAME_KEY, name, target);
    };
}
exports.LIFE_CYCLE_PHASE_KEY = 'phase';
function LifeCycle(name) {
    return (target) => {
        Reflect.defineMetadata(exports.LIFE_CYCLE_PHASE_KEY, name, target);
    };
}
exports.EXTENSION_EXTEND_SERVICE_PREFIX = 'extension_extend_service';
exports.MOCK_EXTENSION_EXTEND_PROXY_IDENTIFIER = (0, ide_connection_1.createExtHostContextProxyIdentifier)('mock_extension_extend_proxy_identifier');
exports.WorkerHostAPIIdentifier = {
    ExtWorkerHostExtensionService: (0, ide_connection_1.createExtHostContextProxyIdentifier)('ExtWorkerHostExtensionService'),
};
var ProcessMessageType;
(function (ProcessMessageType) {
    ProcessMessageType[ProcessMessageType["REPORTER"] = 0] = "REPORTER";
})(ProcessMessageType || (exports.ProcessMessageType = ProcessMessageType = {}));
var EXTENSION_ENABLE;
(function (EXTENSION_ENABLE) {
    EXTENSION_ENABLE[EXTENSION_ENABLE["ENABLE"] = 1] = "ENABLE";
    EXTENSION_ENABLE[EXTENSION_ENABLE["DISABLE"] = 0] = "DISABLE";
})(EXTENSION_ENABLE || (exports.EXTENSION_ENABLE = EXTENSION_ENABLE = {}));
// 广播插件事件
exports.EMIT_EXT_HOST_EVENT = {
    id: 'sumi-extension:ext-host-event',
};
function getExtensionId(extensionId) {
    return extensionId.toLowerCase();
}
var ExtensionHostKind;
(function (ExtensionHostKind) {
    ExtensionHostKind[ExtensionHostKind["NODE_HOST"] = 1] = "NODE_HOST";
    ExtensionHostKind[ExtensionHostKind["WORKER_HOST"] = 2] = "WORKER_HOST";
})(ExtensionHostKind || (exports.ExtensionHostKind = ExtensionHostKind = {}));
exports.ExtensionHostProfilerServicePath = 'ExtensionHostProfilerService';
exports.ExtensionHostProfilerServiceToken = Symbol('ExtensionHostProfilerService');
var OutputType;
(function (OutputType) {
    OutputType[OutputType["STDOUT"] = 0] = "STDOUT";
    OutputType[OutputType["STDERR"] = 1] = "STDERR";
})(OutputType || (exports.OutputType = OutputType = {}));
exports.IExtensionHostManager = Symbol('IExtensionHostManager');
/**
 * 以下都是 fork 新的插件子进程的时候，传入的命令行参数的 key
 */
exports.KT_PROCESS_SOCK_OPTION_KEY = 'kt-process-sock-option';
exports.KT_PROCESS_PRELOAD_KEY = 'kt-process-preload';
exports.KT_APP_CONFIG_KEY = 'kt-app-config';
function validateTypeOrModifier(contribution, extensionPoint, logger) {
    if (typeof contribution.id !== 'string' || contribution.id.length === 0) {
        logger.error("'configuration.{0}.id' must be defined and can not be empty", extensionPoint);
        return false;
    }
    if (!contribution.id.match(semantic_tokens_registry_1.typeAndModifierIdPattern)) {
        logger.error("'configuration.{0}.id' must follow the pattern letterOrDigit[-_letterOrDigit]*");
        return false;
    }
    const superType = contribution.superType;
    if (superType && !superType.match(semantic_tokens_registry_1.typeAndModifierIdPattern)) {
        logger.error("'configuration.{0}.superType' must follow the pattern letterOrDigit[-_letterOrDigit]*", extensionPoint);
        return false;
    }
    if (typeof contribution.description !== 'string' || contribution.id.length === 0) {
        logger.error("'configuration.{0}.description' must be defined and can not be empty", extensionPoint);
        return false;
    }
    return true;
}
var CompletionEventsType;
(function (CompletionEventsType) {
    CompletionEventsType.onLink = 'onLink';
    CompletionEventsType.onEvent = 'onEvent';
    CompletionEventsType.onView = 'onView';
    CompletionEventsType.onSettingChanged = 'onSettingChanged';
    CompletionEventsType.onContext = 'onContext';
    CompletionEventsType.onStepSelected = 'onStepSelected';
    CompletionEventsType.stepSelected = 'stepSelected';
    CompletionEventsType.onCommand = 'onCommand';
    CompletionEventsType.onExtensionInstalled = 'onExtensionInstalled';
    CompletionEventsType.extensionInstalled = 'extensionInstalled';
})(CompletionEventsType || (exports.CompletionEventsType = CompletionEventsType = {}));
// #endregion Walkthroughs
//# sourceMappingURL=extension.js.map