"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ScriptInfoGeneratorTest = exports.CommonTermsSet = exports.CommonTerms = void 0;
const ProjectInfoItem_1 = require("./ProjectInfoItem");
const esprima_next_1 = require("esprima-next");
const ProjectInfoUtilities_1 = require("./ProjectInfoUtilities");
const IProjectItemData_1 = require("../app/IProjectItemData");
const Log_1 = require("../core/Log");
const IInfoItemData_1 = require("./IInfoItemData");
const Database_1 = require("../minecraft/Database");
exports.CommonTerms = [
    "undefined",
    "type",
    "name",
    "error",
    "equals",
    "value",
    "length",
    "index",
    "String",
    "number",
    "width",
    "height",
    "count",
    "event",
    "string",
    "text",
    "object",
];
exports.CommonTermsSet = new Set(exports.CommonTerms);
var ScriptInfoGeneratorTest;
(function (ScriptInfoGeneratorTest) {
    ScriptInfoGeneratorTest[ScriptInfoGeneratorTest["apisUsed"] = 101] = "apisUsed";
})(ScriptInfoGeneratorTest = exports.ScriptInfoGeneratorTest || (exports.ScriptInfoGeneratorTest = {}));
class ScriptInfoGenerator {
    id = "SCRIPT";
    title = "Script";
    canAlwaysProcess = true;
    minecraftTokens = {};
    generatedTokens = false;
    getTopicData(topicId) {
        return {
            title: ProjectInfoUtilities_1.default.getTitleFromEnum(ScriptInfoGeneratorTest, topicId),
        };
    }
    async _generateTokens() {
        await Database_1.default.loadStable20ScriptTypes();
        const typeDefs = Database_1.default.stable20TypeDefs;
        if (typeDefs) {
            for (const typeDef of typeDefs.typeDefs) {
                const typeDefContent = typeDef.content.join("\r\n");
                let name = typeDef.name;
                this.minecraftTokens[name] = {
                    typeDef: typeDef,
                };
                const slashIndex = name.indexOf("/");
                if (slashIndex >= 0) {
                    this.minecraftTokens[name.substring(0, slashIndex)] = {
                        typeDef: typeDef,
                    };
                    this.minecraftTokens[name.substring(slashIndex + 1)] = {
                        typeDef: typeDef,
                    };
                }
                const tokens = this.getAllTokens(typeDefContent);
                for (const tok of tokens) {
                    this.minecraftTokens[tok] = {
                        typeDef: typeDef,
                    };
                }
            }
        }
    }
    async generate(project, contentIndex) {
        const items = [];
        const scriptTokensPi = new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.featureAggregate, this.id, ScriptInfoGeneratorTest.apisUsed, ProjectInfoUtilities_1.default.getTitleFromEnum(ScriptInfoGeneratorTest, ScriptInfoGeneratorTest.apisUsed));
        items.push(scriptTokensPi);
        if (!this.generatedTokens) {
            await this._generateTokens();
        }
        await Database_1.default.loadStable20ScriptTypes();
        const itemsCopy = project.getItemsCopy();
        for (let i = 0; i < itemsCopy.length; i++) {
            const pi = itemsCopy[i];
            if (pi.itemType === IProjectItemData_1.ProjectItemType.js) {
                await pi.ensureFileStorage();
                if (pi.primaryFile) {
                    await pi.primaryFile.loadContent();
                    const content = pi.primaryFile.content;
                    if (content && typeof content === "string") {
                        this.parseJsContent(scriptTokensPi, content);
                    }
                }
            }
        }
        return items;
    }
    getAllTokens(content) {
        const tokens = [];
        const tokensSet = new Set();
        try {
            const results = esprima_next_1.default.tokenize(content);
            if (results) {
                for (const token of results) {
                    if ((token.type === "Identifier" || token.type === "String") && token.value && token.value.length > 3) {
                        let tok = token.value.trim();
                        if (tok.startsWith("'") && tok.endsWith("'")) {
                            tok = tok.substring(1, tok.length - 1);
                        }
                        else if (tok.startsWith("'") && tok.endsWith("'")) {
                            tok = tok.substring(1, tok.length - 1);
                        }
                        if (token.type === "Identifier" && tok !== "from" && !tokensSet.has(tok) && !exports.CommonTermsSet.has(tok)) {
                            tokens.push(tok);
                            tokensSet.add(tok);
                        }
                        else if (token.type === "String" &&
                            !exports.CommonTermsSet.has(tok) &&
                            (tok.startsWith("minecraft:") || tok.startsWith("@minecraft")) &&
                            !tokensSet.has(tok)) {
                            tokens.push(tok);
                            tokensSet.add(tok);
                        }
                    }
                }
            }
        }
        catch (e) {
            Log_1.default.debugAlert("JS parsing error:" + e);
        }
        return tokens;
    }
    parseJsContent(scriptTokensPi, content) {
        let tokens = this.getAllTokens(content);
        for (const token of tokens) {
            if (this.minecraftTokens[token] !== undefined) {
                scriptTokensPi.incrementFeature(token);
            }
        }
    }
    summarize(info, infoSet) {
        const scriptItems = infoSet.getItems(this.id, ScriptInfoGeneratorTest.apisUsed);
        info.apisUsed = [];
        const apisUsedSet = new Set();
        for (const scriptItem of scriptItems) {
            let scriptTokens = scriptItem.featureSets;
            if (scriptTokens) {
                for (const scriptToken in scriptTokens) {
                    if (!apisUsedSet.has(scriptToken) && !exports.CommonTermsSet.has(scriptToken)) {
                        info.apisUsed.push(scriptToken);
                        apisUsedSet.add(scriptToken);
                    }
                }
            }
        }
        info.apisUsed.sort();
    }
}
exports.default = ScriptInfoGenerator;

//# sourceMappingURL=../maps/info/ScriptInfoGenerator.js.map
