"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
const ProjectInfoItem_1 = require("../info/ProjectInfoItem");
const IProjectItemData_1 = require("../app/IProjectItemData");
const IInfoItemData_1 = require("../info/IInfoItemData");
const BehaviorManifestDefinition_1 = require("../minecraft/BehaviorManifestDefinition");
const NpmPackageDefinition_1 = require("../devproject/NpmPackageDefinition");
const Database_1 = require("../minecraft/Database");
const ProjectUpdateResult_1 = require("../updates/ProjectUpdateResult");
const IUpdateResult_1 = require("../updates/IUpdateResult");
const EnvSettings_1 = require("../devproject/EnvSettings");
const Utilities_1 = require("../core/Utilities");
class ScriptModuleManager {
    id = "SCRIPTMODULE";
    title = "Script Modules";
    modulesInUse = {};
    packRegsInUse = {};
    getTopicData(topicId) {
        return {
            title: topicId.toString(),
        };
    }
    getUpdaterData(topicId) {
        return {
            title: topicId.toString(),
        };
    }
    summarize(info, infoSet) { }
    async generateProjectState(project) {
        const items = [];
        this.modulesInUse = {};
        this.packRegsInUse = {};
        const itemsCopy = project.getItemsCopy();
        for (let i = 0; i < itemsCopy.length; i++) {
            const pi = itemsCopy[i];
            if (pi.itemType === IProjectItemData_1.ProjectItemType.behaviorPackManifestJson) {
                if (!pi.isContentLoaded) {
                    await pi.loadContent();
                }
                if (pi.primaryFile) {
                    const bpManifest = await BehaviorManifestDefinition_1.default.ensureOnFile(pi.primaryFile);
                    if (bpManifest && bpManifest.definition && bpManifest.definition.dependencies) {
                        const deps = bpManifest.definition.dependencies;
                        for (let j = 0; j < deps.length; j++) {
                            const dep = deps[j];
                            if (dep.module_name && dep.version) {
                                let verStr = "";
                                if (typeof dep.version === "string") {
                                    verStr = dep.version;
                                }
                                else {
                                    verStr = dep.version.join(".");
                                }
                                if (Utilities_1.default.isUsableAsObjectKey(dep.module_name)) {
                                    if (!this.modulesInUse[dep.module_name]) {
                                        this.modulesInUse[dep.module_name] = [];
                                    }
                                    items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.info, this.id, 100, "Behavior pack dependency on " + verStr + " at " + dep.module_name, pi, verStr, dep.module_name));
                                    this.modulesInUse[dep.module_name].push({ version: verStr, manifest: bpManifest, item: pi });
                                }
                            }
                        }
                    }
                }
            }
            else if (pi.itemType === IProjectItemData_1.ProjectItemType.packageJson) {
                if (!pi.isContentLoaded) {
                    await pi.loadContent();
                }
                if (pi.primaryFile) {
                    const npmPackageJson = await NpmPackageDefinition_1.default.ensureOnFile(pi.primaryFile);
                    if (npmPackageJson && npmPackageJson.definition) {
                        const deps = npmPackageJson.definition.dependencies;
                        const devDeps = npmPackageJson.definition.devDependencies;
                        if (deps) {
                            for (const depKey in deps) {
                                if (depKey.startsWith("@minecraft/")) {
                                    if (!this.packRegsInUse[depKey]) {
                                        this.packRegsInUse[depKey] = [];
                                    }
                                    this.packRegsInUse[depKey].push({
                                        package: npmPackageJson,
                                        isDevDependency: false,
                                        version: deps[depKey],
                                    });
                                    items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.info, this.id, 101, "Package.json registers usage of " + depKey + " at " + deps[depKey], pi, deps[depKey], depKey));
                                }
                            }
                        }
                        if (devDeps) {
                            for (const depKey in devDeps) {
                                if (depKey.startsWith("@minecraft/")) {
                                    if (!this.packRegsInUse[depKey]) {
                                        this.packRegsInUse[depKey] = [];
                                    }
                                    this.packRegsInUse[depKey].push({
                                        package: npmPackageJson,
                                        isDevDependency: true,
                                        version: devDeps[depKey],
                                    });
                                    items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.info, this.id, 102, "Package.json registers developer usage of " + depKey + " at " + devDeps[depKey], pi, devDeps[depKey], depKey));
                                }
                            }
                        }
                    }
                }
            }
            else if (pi.itemType === IProjectItemData_1.ProjectItemType.env) {
                if (!pi.isContentLoaded) {
                    await pi.loadContent();
                }
                if (pi.primaryFile) {
                    const envFile = await EnvSettings_1.default.ensureOnFile(pi.primaryFile);
                    await envFile?.ensureEnvFile(project);
                }
            }
        }
        return items;
    }
    async generate(project, contentIndex) {
        const items = await this.generateProjectState(project);
        let hasPackageJson = false;
        for (const item of project.items) {
            if (item.itemType === IProjectItemData_1.ProjectItemType.packageJson) {
                hasPackageJson = true;
            }
        }
        for (const moduleName in this.modulesInUse) {
            const moduleInfo = this.modulesInUse[moduleName];
            if (moduleInfo) {
                const npmModule = await Database_1.default.getModuleDescriptor(moduleName);
                if (npmModule) {
                    if (npmModule.betaVersion) {
                        for (let k = 0; k < moduleInfo.length; k++) {
                            const mod = moduleInfo[k];
                            if (mod.version.indexOf("-beta") >= 0) {
                                if (!mod.version.startsWith(npmModule.betaVersion)) {
                                    items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, 114, "For " +
                                        moduleName +
                                        ", using an out of date beta version " +
                                        mod.version +
                                        " compared to the current version", mod.item, mod.version));
                                }
                            }
                        }
                    }
                    const packReg = this.packRegsInUse[moduleName];
                    if (!packReg && hasPackageJson) {
                        items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, 110, "Could not find an package.json registration for " + moduleName, undefined, moduleName));
                    }
                }
                else if (hasPackageJson) {
                    items.push(new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.error, this.id, 111, "Could not find an NPMJS.org NPM module registration for " + moduleName, undefined, moduleName));
                }
            }
        }
        return items;
    }
    async update(project, updateId) {
        const results = [];
        switch (updateId) {
            case 1:
                const localResults = await this.updateModulesToLatestVersion(project);
                results.push(...localResults);
                break;
        }
        return results;
    }
    getUpdateIds() {
        return [1];
    }
    async updateModulesToLatestVersion(project) {
        const results = [];
        await this.generateProjectState(project);
        for (const moduleName in this.modulesInUse) {
            const moduleInfo = this.modulesInUse[moduleName];
            if (moduleInfo) {
                const npmModule = await Database_1.default.getModuleDescriptor(moduleName);
                if (npmModule) {
                    for (let k = 0; k < moduleInfo.length; k++) {
                        const mod = moduleInfo[k];
                        if (mod.version.indexOf("-beta") >= 0) {
                            if (npmModule.betaVersion) {
                                const isChanged = mod.manifest.setModuleVersion(moduleName, npmModule.betaVersion + "-beta");
                                if (isChanged) {
                                    await mod.manifest.save();
                                    results.push(new ProjectUpdateResult_1.default(IUpdateResult_1.UpdateResultType.updatedFile, this.id, 1, "Set module to latest beta version", undefined, npmModule.betaVersion + "-beta"));
                                }
                            }
                        }
                        else if (mod.version.indexOf("-") < 1) {
                            if (npmModule.latest) {
                                mod.manifest.setModuleVersion(moduleName, npmModule.latest);
                                await mod.manifest.save();
                                results.push(new ProjectUpdateResult_1.default(IUpdateResult_1.UpdateResultType.updatedFile, this.id, 1, "Set module to latest stable version", undefined, npmModule.latest));
                            }
                        }
                    }
                }
            }
        }
        return results;
    }
}
exports.default = ScriptModuleManager;

//# sourceMappingURL=../maps/manager/ScriptModuleManager.js.map
