"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MenusContributionPoint = exports.SubmenusContributionPoint = void 0;
exports.parseMenuId = parseMenuId;
exports.parseMenuGroup = parseMenuGroup;
exports.isValidMenuItem = isValidMenuItem;
const tslib_1 = require("tslib");
const di_1 = require("@opensumi/di");
const ide_core_browser_1 = require("@opensumi/ide-core-browser");
const menu_1 = require("@opensumi/ide-core-browser/lib/extensions/schema/menu");
const layout_1 = require("@opensumi/ide-core-browser/lib/layout");
const next_1 = require("@opensumi/ide-core-browser/lib/menu/next");
const ide_editor_1 = require("@opensumi/ide-editor");
const browser_1 = require("@opensumi/ide-editor/lib/browser");
const ide_theme_1 = require("@opensumi/ide-theme");
const theme_service_1 = require("@opensumi/ide-theme/lib/common/theme.service");
const common_1 = require("../../../common");
const types_1 = require("../../types");
function isMenuActionFormat(item) {
    return typeof item.command === 'string';
}
function parseMenuId(value) {
    switch (value) {
        // 以下仅保留对 vscode 部分 menuId 的兼容
        case 'touchBar':
            return next_1.MenuId.TouchBarContext;
        case 'debug/toolBar':
            return next_1.MenuId.DebugToolBar;
        case 'statusBar/windowIndicator':
            return next_1.MenuId.StatusBarWindowIndicatorMenu;
        case 'menuBar/file':
            return next_1.MenuId.MenubarFileMenu;
        default:
            return value;
    }
}
function parseMenuGroup(groupStr) {
    let group;
    let order;
    if (groupStr) {
        const idx = groupStr.lastIndexOf('@');
        if (idx > 0) {
            group = groupStr.substr(0, idx);
            order = Number(groupStr.substr(idx + 1)) || undefined;
        }
        else {
            group = groupStr;
        }
    }
    return [group, order];
}
function isValidMenuItem(item, collector) {
    if (typeof item.command !== 'string') {
        collector.error((0, ide_core_browser_1.formatLocalize)('requirestring', 'command'));
        return false;
    }
    if (item.alt && typeof item.alt !== 'string') {
        collector.error((0, ide_core_browser_1.formatLocalize)('optstring', 'alt'));
        return false;
    }
    if (item.when && typeof item.when !== 'string') {
        collector.error((0, ide_core_browser_1.formatLocalize)('optstring', 'when'));
        return false;
    }
    if (item.group && typeof item.group !== 'string') {
        collector.error((0, ide_core_browser_1.formatLocalize)('optstring', 'group'));
        return false;
    }
    return true;
}
function isValidSubmenuItem(item, collector) {
    if (typeof item.submenu !== 'string') {
        collector.error((0, ide_core_browser_1.formatLocalize)('requirestring', 'property `{0}` is mandatory and must be of type `string`', 'submenu'));
        return false;
    }
    if (item.when && typeof item.when !== 'string') {
        collector.error((0, ide_core_browser_1.formatLocalize)('optstring', 'property `{0}` can be omitted or must be of type `string`', 'when'));
        return false;
    }
    if (item.group && typeof item.group !== 'string') {
        collector.error((0, ide_core_browser_1.formatLocalize)('optstring', 'property `{0}` can be omitted or must be of type `string`', 'group'));
        return false;
    }
    return true;
}
function isValidItems(items, collector) {
    if (!Array.isArray(items)) {
        collector.error((0, ide_core_browser_1.formatLocalize)('requirearray', 'submenu items must be an array'));
        return false;
    }
    for (const item of items) {
        if (isMenuActionFormat(item)) {
            if (!isValidMenuItem(item, collector)) {
                return false;
            }
        }
        else {
            if (!isValidSubmenuItem(item, collector)) {
                return false;
            }
        }
    }
    return true;
}
// vscode contributes#submenus 时, 用来做 submenu item 的 i18n 字符替换
const _submenuDescRegistry = new Map();
let SubmenusContributionPoint = class SubmenusContributionPoint extends common_1.VSCodeContributePoint {
    contribute() {
        for (const contrib of this.contributesMap) {
            const { extensionId, contributes } = contrib;
            _submenuDescRegistry.set(extensionId, contributes);
        }
    }
};
exports.SubmenusContributionPoint = SubmenusContributionPoint;
SubmenusContributionPoint.schema = {};
exports.SubmenusContributionPoint = SubmenusContributionPoint = tslib_1.__decorate([
    (0, di_1.Injectable)(),
    (0, common_1.Contributes)('submenus'),
    (0, common_1.LifeCycle)(3 /* LifeCyclePhase.Starting */)
], SubmenusContributionPoint);
let MenusContributionPoint = class MenusContributionPoint extends common_1.VSCodeContributePoint {
    constructor() {
        super(...arguments);
        this.phase = 2 /* LifeCyclePhase.Initialize */;
    }
    createSyntheticCommandId(menu, prefix) {
        const command = menu.command;
        let id = prefix + command;
        let index = 0;
        while (this.commandRegistry.getCommand(id)) {
            id = prefix + command + ':' + index;
            index++;
        }
        return id;
    }
    getDataFromQuery(query, data) {
        const q = new URLSearchParams(query);
        return q.get(data);
    }
    contribute() {
        const collector = console;
        for (const contrib of this.contributesMap) {
            const { extensionId, contributes } = contrib;
            const extension = this.extensionManageService.getExtensionInstanceByExtId(extensionId);
            if (!extension) {
                continue;
            }
            // menu registration
            for (const menuPosition of Object.keys(contributes)) {
                const menuActions = contributes[menuPosition];
                if (!isValidItems(menuActions, console)) {
                    return;
                }
                const menuId = parseMenuId(menuPosition);
                if ((0, ide_core_browser_1.isUndefined)(menuId)) {
                    collector.warn((0, ide_core_browser_1.formatLocalize)('menuId.invalid', '`{0}` is not a valid menu identifier', menuPosition));
                    return;
                }
                for (const item of menuActions) {
                    if (isMenuActionFormat(item)) {
                        const command = this.commandRegistry.getRawCommand(item.command);
                        // alt 逻辑先不处理
                        const alt = item.alt && this.commandRegistry.getRawCommand(item.alt);
                        if (!command) {
                            collector.error((0, ide_core_browser_1.formatLocalize)('menu.missing.command', menuId, item.command));
                            continue;
                        }
                        if (item.alt && !alt) {
                            collector.warn((0, ide_core_browser_1.formatLocalize)('menu.missing.altCommand', menuId, item.alt));
                        }
                        if (item.command === item.alt) {
                            collector.info((0, ide_core_browser_1.formatLocalize)('menu.dupe.command', menuId, item.command, item.alt));
                        }
                        const [group, order] = parseMenuGroup(item.group);
                        let argsTransformer;
                        if (menuId === next_1.MenuId.EditorTitleContext) {
                            argsTransformer = ({ uri }) => [uri.codeUri];
                        }
                        else if (menuId === next_1.MenuId.EditorTitle) {
                            argsTransformer = (uri, _group, editorUri) => {
                                if (uri.scheme === ide_editor_1.EditorOpenType.diff) {
                                    // 对于 DiffEditor 情况时，尝试通过 query 获取 modified URI 作为首个参数
                                    const modified = this.getDataFromQuery(decodeURIComponent(uri.query), 'modified');
                                    if (modified) {
                                        return [new ide_core_browser_1.URI(modified).codeUri];
                                    }
                                }
                                return [(editorUri === null || editorUri === void 0 ? void 0 : editorUri.codeUri) || uri.codeUri];
                            };
                        }
                        this.addDispose(this.menuRegistry.registerMenuItem(menuId, {
                            command: item.command,
                            alt,
                            group,
                            order,
                            when: item.when,
                            // 以下为 kaitian 扩展部分
                            argsTransformer,
                            type: item.type,
                            toggledWhen: item.toggledWhen,
                            enabledWhen: item.enabledWhen,
                        }));
                    }
                    else {
                        const submenuRegistry = _submenuDescRegistry.get(extensionId);
                        if (!submenuRegistry) {
                            collector.error((0, ide_core_browser_1.localize)('missing.submenu.section', 'Need a submenu contributes firstly', item.submenu));
                            continue;
                        }
                        const submenuDesc = submenuRegistry.find((n) => n.id === item.submenu);
                        if (!submenuDesc) {
                            collector.error((0, ide_core_browser_1.localize)('missing.submenu', "Menu item references a submenu `{0}` which is not defined in the 'submenus' section.", item.submenu));
                            continue;
                        }
                        const [group, order] = parseMenuGroup(item.group);
                        this.addDispose(this.menuRegistry.registerMenuItem(menuId, {
                            submenu: item.submenu,
                            label: this.getLocalizeFromNlsJSON(submenuDesc.label, extensionId),
                            when: item.when,
                            group,
                            order,
                            iconClass: submenuDesc.icon && this.toIconClass(submenuDesc.icon, ide_theme_1.IconType.Background, extension.path),
                        }));
                    }
                }
            }
        }
    }
};
exports.MenusContributionPoint = MenusContributionPoint;
MenusContributionPoint.schema = menu_1.menus.schema;
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_browser_1.CommandRegistry),
    tslib_1.__metadata("design:type", Object)
], MenusContributionPoint.prototype, "commandRegistry", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_browser_1.CommandService),
    tslib_1.__metadata("design:type", Object)
], MenusContributionPoint.prototype, "commandService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_browser_1.ILogger),
    tslib_1.__metadata("design:type", Object)
], MenusContributionPoint.prototype, "logger", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(next_1.IMenuRegistry),
    tslib_1.__metadata("design:type", next_1.IMenuRegistry)
], MenusContributionPoint.prototype, "menuRegistry", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(),
    tslib_1.__metadata("design:type", layout_1.ToolbarRegistry)
], MenusContributionPoint.prototype, "toolBarRegistry", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(browser_1.IEditorActionRegistry),
    tslib_1.__metadata("design:type", Object)
], MenusContributionPoint.prototype, "editorActionRegistry", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(ide_core_browser_1.IContextKeyService),
    tslib_1.__metadata("design:type", Object)
], MenusContributionPoint.prototype, "contextKeyService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(theme_service_1.IIconService),
    tslib_1.__metadata("design:type", Object)
], MenusContributionPoint.prototype, "iconService", void 0);
tslib_1.__decorate([
    (0, di_1.Autowired)(types_1.AbstractExtInstanceManagementService),
    tslib_1.__metadata("design:type", types_1.AbstractExtInstanceManagementService)
], MenusContributionPoint.prototype, "extensionManageService", void 0);
exports.MenusContributionPoint = MenusContributionPoint = tslib_1.__decorate([
    (0, di_1.Injectable)(),
    (0, common_1.Contributes)('menus'),
    (0, common_1.LifeCycle)(3 /* LifeCyclePhase.Starting */)
], MenusContributionPoint);
//# sourceMappingURL=menu.js.map