"use strict";
/**********************************************************************
 * Copyright (c) 2021 Red Hat, Inc.
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 ***********************************************************************/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PluginRegistryResolver = void 0;
const jsYaml = require("js-yaml");
const inversify_1 = require("inversify");
const url_fetcher_1 = require("../fetch/url-fetcher");
/**
 * Resolve plug-ins by grabbing the definition from the plug-in registry.
 */
let PluginRegistryResolver = class PluginRegistryResolver {
    async resolve(vSCodeExtensionEntries) {
        // resolve extensions references
        await Promise.all(vSCodeExtensionEntries.map(entry => this.resolveEntry(entry)));
        // now resolved dependencies
        await this.resolveDependencies(vSCodeExtensionEntries);
    }
    // Iterate on dependencies
    async resolveDependencies(vSCodeExtensionEntries) {
        // list of all dependencies
        const allDependencies = vSCodeExtensionEntries
            .map(extension => extension.dependencies || [])
            // flatten the array of array
            .reduce((acc, val) => acc.concat(val), []);
        const uniqueDependencies = [...new Set(allDependencies)];
        // list of all dependencies not yet analyzed (because not yet in the list)
        const toAnalyzeDependenciesIds = uniqueDependencies.filter(dependency => !vSCodeExtensionEntries.some(entry => entry.id === `${dependency.replace(/\./g, '/')}/latest`));
        // map new dependencies
        const toAnalyzeDependencies = toAnalyzeDependenciesIds.map(name => ({
            id: `${name.replace(/\./g, '/')}/latest`,
            resolved: false,
            optional: true,
            extensions: [],
        }));
        // resolve these new dependencies
        await Promise.all(toAnalyzeDependencies.map(entry => this.resolveEntry(entry)));
        // add new extensions being resolved
        vSCodeExtensionEntries.push(...toAnalyzeDependencies);
        // new dependencies, check again if new dependencies are there
        if (toAnalyzeDependencies.length > 0) {
            await this.resolveDependencies(vSCodeExtensionEntries);
        }
    }
    // FQN id (like eclipse/che-theia/next)
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    async loadDevfilePlugin(devfileId) {
        const devfileUrl = `${this.pluginRegistryUrl}/plugins/${devfileId}/devfile.yaml`;
        const devfileContent = await this.urlFetcher.fetchText(devfileUrl);
        return jsYaml.load(devfileContent);
    }
    // check if extension is not resolved
    // if not, reach plugin-registry
    async resolveEntry(vSCodeExtensionEntry) {
        // skip already resolved
        if (vSCodeExtensionEntry.resolved === true) {
            return;
        }
        // grab the content from the plugin registry
        // plugin registry url is with the format "https://plugin-registry.com/v3"
        const url = `${this.pluginRegistryUrl}/plugins/${vSCodeExtensionEntry.id}/che-theia-plugin.yaml`;
        // let's propagate the error if the plugin definition does not exist
        const cheTheiaPluginYamlContent = await this.urlFetcher.fetchTextOptionalContent(url);
        if (!cheTheiaPluginYamlContent) {
            if (vSCodeExtensionEntry.optional === true) {
                console.error(`${vSCodeExtensionEntry.id} is missing on the plug-in registry but it is flagged as optional, skipping it`);
                return;
            }
            else {
                throw new Error(`${vSCodeExtensionEntry.id} is a mandatory plug-in but definition is not found on the plug-in registry. Aborting !`);
            }
        }
        const cheTheiaPluginYaml = jsYaml.load(cheTheiaPluginYamlContent);
        // resolve now the extension
        vSCodeExtensionEntry.resolved = true;
        vSCodeExtensionEntry.extensions = cheTheiaPluginYaml.extensions;
        const sidecar = cheTheiaPluginYaml.sidecar;
        if (sidecar) {
            vSCodeExtensionEntry.sidecarName = sidecar.name;
            delete sidecar.name;
        }
        const vSCodeExtensionEntrySidecar = vSCodeExtensionEntry.sidecar;
        vSCodeExtensionEntry.sidecar = sidecar;
        //overwrite cpu and memory limit in sidecar
        if (vSCodeExtensionEntrySidecar === null || vSCodeExtensionEntrySidecar === void 0 ? void 0 : vSCodeExtensionEntrySidecar.cpuLimit) {
            vSCodeExtensionEntry.sidecar.cpuLimit = vSCodeExtensionEntrySidecar.cpuLimit;
        }
        if (vSCodeExtensionEntrySidecar === null || vSCodeExtensionEntrySidecar === void 0 ? void 0 : vSCodeExtensionEntrySidecar.memoryLimit) {
            vSCodeExtensionEntry.sidecar.memoryLimit = vSCodeExtensionEntrySidecar.memoryLimit;
        }
        // merge preferences
        // a preference from entry should overwrite a preference from registry which has identical key
        const pluginPreferences = cheTheiaPluginYaml.preferences || {};
        const overriddenPreferences = vSCodeExtensionEntry.preferences || {};
        const allPreferences = Object.assign(Object.assign({}, pluginPreferences), overriddenPreferences);
        vSCodeExtensionEntry.preferences = allPreferences;
        vSCodeExtensionEntry.dependencies = cheTheiaPluginYaml.dependencies;
    }
};
__decorate([
    inversify_1.inject('string'),
    inversify_1.named('PLUGIN_REGISTRY_URL'),
    __metadata("design:type", String)
], PluginRegistryResolver.prototype, "pluginRegistryUrl", void 0);
__decorate([
    inversify_1.inject(url_fetcher_1.UrlFetcher),
    __metadata("design:type", url_fetcher_1.UrlFetcher)
], PluginRegistryResolver.prototype, "urlFetcher", void 0);
PluginRegistryResolver = __decorate([
    inversify_1.injectable()
], PluginRegistryResolver);
exports.PluginRegistryResolver = PluginRegistryResolver;
//# sourceMappingURL=plugin-registry-resolver.js.map