"use strict";
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.JsonFileTagsInfoGeneratorTest = void 0;
const ProjectInfoItem_1 = require("./ProjectInfoItem");
const IInfoItemData_1 = require("./IInfoItemData");
const StorageUtilities_1 = require("../storage/StorageUtilities");
const ZipStorage_1 = require("../storage/ZipStorage");
const ContentIndex_1 = require("../core/ContentIndex");
const ProjectInfoUtilities_1 = require("./ProjectInfoUtilities");
const tagAllowList = ["render_method", "min_difficulty", "cause", "effect_name", "entity_type", "event_name"];
const numericAllowList = ["max_stack_size"];
const boolAllowList = ["fire_immune", "burns_in_daylight", "hand_equipped", "stacked_by_data"];
const inspectTagList = [
    "minecraft:behavior.follow_mob",
    "minecraft:behavior.float_wander",
    "minecraft:behavior.tempt",
];
var JsonFileTagsInfoGeneratorTest;
(function (JsonFileTagsInfoGeneratorTest) {
    JsonFileTagsInfoGeneratorTest[JsonFileTagsInfoGeneratorTest["entityType"] = 101] = "entityType";
    JsonFileTagsInfoGeneratorTest[JsonFileTagsInfoGeneratorTest["blockType"] = 102] = "blockType";
    JsonFileTagsInfoGeneratorTest[JsonFileTagsInfoGeneratorTest["itemType"] = 103] = "itemType";
    JsonFileTagsInfoGeneratorTest[JsonFileTagsInfoGeneratorTest["terrainTexture"] = 104] = "terrainTexture";
    JsonFileTagsInfoGeneratorTest[JsonFileTagsInfoGeneratorTest["itemTexture"] = 105] = "itemTexture";
    JsonFileTagsInfoGeneratorTest[JsonFileTagsInfoGeneratorTest["soundDefinition"] = 106] = "soundDefinition";
    JsonFileTagsInfoGeneratorTest[JsonFileTagsInfoGeneratorTest["musicDefinition"] = 107] = "musicDefinition";
    JsonFileTagsInfoGeneratorTest[JsonFileTagsInfoGeneratorTest["sound"] = 108] = "sound";
})(JsonFileTagsInfoGeneratorTest = exports.JsonFileTagsInfoGeneratorTest || (exports.JsonFileTagsInfoGeneratorTest = {}));
class JsonFileTagsInfoGenerator {
    id = "JSONTAGS";
    title = "JSON Tags";
    canAlwaysProcess = true;
    getTopicData(topicId) {
        return {
            title: ProjectInfoUtilities_1.default.getTitleFromEnum(JsonFileTagsInfoGeneratorTest, topicId),
        };
    }
    async generate(project, contentIndex) {
        const items = [];
        if (project.projectFolder) {
            await this.generateFromFolder(project, project.projectFolder, items, contentIndex);
        }
        return items;
    }
    summarize(info, infoSet) {
        const entityTypeComponents = infoSet.getItems(this.id, JsonFileTagsInfoGeneratorTest.entityType);
        const blockTypeComponents = infoSet.getItems(this.id, JsonFileTagsInfoGeneratorTest.blockType);
        const itemTypeComponents = infoSet.getItems(this.id, JsonFileTagsInfoGeneratorTest.itemType);
        info.entityTypeComponents = [];
        info.blockTypeComponents = [];
        info.itemTypeComponents = [];
        for (const entityTypeComponent of entityTypeComponents) {
            let entityComponentSets = entityTypeComponent.featureSets;
            if (entityComponentSets) {
                const ecInCg = entityComponentSets["Components Used in Component Groups"];
                if (ecInCg) {
                    for (let cgId in ecInCg) {
                        if (cgId.startsWith("minecraft:")) {
                            cgId = cgId.substring(10);
                        }
                        if (!info.entityTypeComponents.includes(cgId)) {
                            info.entityTypeComponents.push(cgId);
                        }
                    }
                }
                const defaultEcInCg = entityComponentSets["Default Components"];
                if (defaultEcInCg) {
                    for (let cgId in defaultEcInCg) {
                        if (cgId.startsWith("minecraft:")) {
                            cgId = cgId.substring(10);
                        }
                        if (!info.entityTypeComponents.includes(cgId)) {
                            info.entityTypeComponents.push(cgId);
                        }
                    }
                }
            }
        }
        for (const blockTypeComponent of blockTypeComponents) {
            let blockComponentSets = blockTypeComponent.featureSets;
            if (blockComponentSets) {
                const blockTypeComponents = blockComponentSets["Block Default Components"];
                if (blockTypeComponents) {
                    for (let cgId in blockTypeComponents) {
                        if (cgId.startsWith("minecraft:")) {
                            cgId = cgId.substring(10);
                        }
                        if (!info.blockTypeComponents.includes(cgId)) {
                            info.blockTypeComponents.push(cgId);
                        }
                    }
                }
                const blockPermutationTypeComponents = blockComponentSets["Block Permutation Components"];
                if (blockPermutationTypeComponents) {
                    for (let cgId in blockPermutationTypeComponents) {
                        if (cgId.startsWith("minecraft:")) {
                            cgId = cgId.substring(10);
                        }
                        if (!info.blockTypeComponents.includes(cgId)) {
                            info.blockTypeComponents.push(cgId);
                        }
                    }
                }
            }
        }
        for (const itemTypeComponent of itemTypeComponents) {
            let itemComponentSets = itemTypeComponent.featureSets;
            if (itemComponentSets) {
                const itemTypeComponents = itemComponentSets["Components"];
                if (itemTypeComponents) {
                    for (let cgId in itemTypeComponents) {
                        if (cgId.startsWith("minecraft:")) {
                            cgId = cgId.substring(10);
                        }
                        if (!info.itemTypeComponents.includes(cgId)) {
                            info.itemTypeComponents.push(cgId);
                        }
                    }
                }
            }
        }
        info.entityTypeComponents.sort();
        info.itemTypeComponents.sort();
        info.blockTypeComponents.sort();
    }
    async generateFromFolder(project, folder, items, index) {
        if (!folder.isLoaded) {
            await folder.load();
        }
        for (const fileName in folder.files) {
            const baseType = StorageUtilities_1.default.getTypeFromName(fileName);
            const file = folder.files[fileName];
            if (baseType === "json" && file) {
                await this.generateFromFile(project, file, items, index);
            }
            else if (StorageUtilities_1.default.isContainerFile(fileName) && file) {
                if (!file.isContentLoaded) {
                    await file.loadContent();
                }
                if (file.content && file.content instanceof Uint8Array) {
                    if (!file.fileContainerStorage) {
                        const zipStorage = new ZipStorage_1.default();
                        zipStorage.storagePath = file.storageRelativePath + "#";
                        await zipStorage.loadFromUint8Array(file.content, file.name);
                        file.fileContainerStorage = zipStorage;
                    }
                    if (file.fileContainerStorage) {
                        await this.generateFromFolder(project, file.fileContainerStorage.rootFolder, items, index);
                    }
                }
            }
        }
        for (const folderName in folder.folders) {
            const childFolder = folder.folders[folderName];
            if (childFolder && !folder.errorStatus) {
                await this.generateFromFolder(project, childFolder, items, index);
            }
        }
    }
    async generateFromFile(project, file, items, index) {
        const srPath = file.storageRelativePath.toLowerCase();
        if (srPath.indexOf("/entities/") >= 0 && !srPath.endsWith(".entity.json")) {
            const pi = new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.info, this.id, JsonFileTagsInfoGeneratorTest.entityType, "Entity file", project.getItemByExtendedOrProjectPath(file.storageRelativePath), file.storageRelativePath);
            if (!file.isContentLoaded) {
                await file.loadContent(false);
            }
            const jsonO = StorageUtilities_1.default.getJsonObject(file);
            if (jsonO !== undefined) {
                const entityNode = jsonO["minecraft:entity"];
                if (entityNode) {
                    await this.addSubTags(pi, "Default Components", index, ContentIndex_1.AnnotationCategory.entityComponentDependent, entityNode["components"]);
                    const compGroupsNode = entityNode["component_groups"];
                    if (compGroupsNode) {
                        for (const compNodeName in compGroupsNode) {
                            await this.addSubTags(pi, "Components Used in Component Groups", index, ContentIndex_1.AnnotationCategory.entityComponentDependentInGroup, compGroupsNode[compNodeName]);
                        }
                    }
                    const eventsNode = entityNode["events"];
                    if (eventsNode) {
                        for (const evNodeName in eventsNode) {
                            await this.addSubTags(pi, "Entity Events", index, ContentIndex_1.AnnotationCategory.entityEvent, eventsNode[evNodeName]);
                        }
                    }
                }
            }
            items.push(pi);
        }
        if (srPath.indexOf("/items/") >= 0) {
            const pi = new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.info, this.id, JsonFileTagsInfoGeneratorTest.itemType, "Item file", project.getItemByExtendedOrProjectPath(file.storageRelativePath), file.storageRelativePath);
            if (!file.isContentLoaded) {
                await file.loadContent(false);
            }
            const jsonO = StorageUtilities_1.default.getJsonObject(file);
            if (jsonO !== undefined) {
                const itemNode = jsonO["minecraft:item"];
                if (itemNode) {
                    await this.addSubTags(pi, "Components", index, ContentIndex_1.AnnotationCategory.itemComponentDependent, itemNode["components"]);
                }
            }
            items.push(pi);
        }
        if (srPath.indexOf("/blocks/") >= 0) {
            const pi = new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.info, this.id, JsonFileTagsInfoGeneratorTest.blockType, "Block file", project.getItemByExtendedOrProjectPath(file.storageRelativePath), file.storageRelativePath);
            if (!file.isContentLoaded) {
                await file.loadContent(false);
            }
            const jsonO = StorageUtilities_1.default.getJsonObject(file);
            if (jsonO) {
                const blockNode = jsonO["minecraft:block"];
                if (blockNode) {
                    await this.addSubTags(pi, "Block Default Components", index, ContentIndex_1.AnnotationCategory.blockComponentDependent, blockNode["components"]);
                    const descriptionNode = blockNode["description"];
                    if (descriptionNode) {
                        let stateNode = descriptionNode["states"];
                        if (stateNode === undefined) {
                            stateNode = descriptionNode["properties"];
                        }
                        let permutations = 0;
                        if (stateNode) {
                            for (const obj in stateNode) {
                                const val = stateNode[obj];
                                if (val && val.length) {
                                    if (permutations === 0) {
                                        permutations = val.length;
                                    }
                                    else {
                                        permutations *= val.length;
                                    }
                                    pi.maxFeature("Permutation", "Values per property", val.length);
                                }
                            }
                        }
                        let traitsNode = descriptionNode["traits"];
                        if (traitsNode) {
                            if (traitsNode["minecraft:placement_direction"]) {
                                const enabledStates = traitsNode["minecraft:placement_direction"]["enabled_states"];
                                if (enabledStates && enabledStates.includes("minecraft:cardinal_direction")) {
                                    if (permutations === 0) {
                                        permutations = 4;
                                    }
                                    else {
                                        permutations *= 4;
                                    }
                                }
                                if (enabledStates && enabledStates.includes("minecraft:facing_direction")) {
                                    if (permutations === 0) {
                                        permutations = 6;
                                    }
                                    else {
                                        permutations *= 6;
                                    }
                                }
                            }
                            if (traitsNode["minecraft:placement_position"]) {
                                const enabledStates = traitsNode["minecraft:placement_position"]["enabled_states"];
                                if (enabledStates && enabledStates.includes("minecraft:block_face")) {
                                    if (permutations === 0) {
                                        permutations = 6;
                                    }
                                    else {
                                        permutations *= 6;
                                    }
                                }
                                if (enabledStates && enabledStates.includes("minecraft:vertical_half")) {
                                    if (permutations === 0) {
                                        permutations = 2;
                                    }
                                    else {
                                        permutations *= 2;
                                    }
                                }
                            }
                        }
                        if (stateNode || traitsNode) {
                            pi.maxFeature("Permutation", "Values per type", permutations);
                            pi.incrementFeature("Permutation", "Values", permutations);
                        }
                    }
                    const permsNode = blockNode["permutations"];
                    if (permsNode) {
                        for (const permNode of permsNode) {
                            const permComponentsNode = permNode["components"];
                            if (permComponentsNode) {
                                await this.addSubTags(pi, "Block Permutation Components", index, ContentIndex_1.AnnotationCategory.blockComponentDependentInPermutation, permComponentsNode);
                            }
                        }
                    }
                }
            }
            items.push(pi);
        }
        if (srPath.indexOf("/textures/terrain_texture.json") >= 0) {
            const pi = new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.info, this.id, JsonFileTagsInfoGeneratorTest.terrainTexture, "Terrrain texture file", project.getItemByExtendedOrProjectPath(file.storageRelativePath), file.storageRelativePath);
            if (!file.isContentLoaded) {
                await file.loadContent(false);
            }
            const jsonO = StorageUtilities_1.default.getJsonObject(file);
            if (jsonO && jsonO.texture_data) {
                await this.addSubTags(pi, "Terrain Texture Elements", index, ContentIndex_1.AnnotationCategory.terrainTextureSource, jsonO.texture_data, true);
            }
            items.push(pi);
        }
        else if (srPath.indexOf("/textures/item_texture.json") >= 0) {
            const pi = new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.info, this.id, JsonFileTagsInfoGeneratorTest.itemTexture, "Item texture file", project.getItemByExtendedOrProjectPath(file.storageRelativePath), file.storageRelativePath);
            await file.loadContent(false);
            const jsonO = StorageUtilities_1.default.getJsonObject(file);
            if (jsonO && jsonO.texture_data) {
                await this.addSubTags(pi, "Item Texture Elements", index, ContentIndex_1.AnnotationCategory.itemTextureSource, jsonO.texture_data, true);
            }
            items.push(pi);
        }
        else if (srPath.indexOf("/sounds/sound_definitions.json") >= 0) {
            const pi = new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.info, this.id, JsonFileTagsInfoGeneratorTest.soundDefinition, "Sound definitions file", project.getItemByExtendedOrProjectPath(file.storageRelativePath), file.storageRelativePath);
            if (!file.isContentLoaded) {
                await file.loadContent(false);
            }
            const jsonO = StorageUtilities_1.default.getJsonObject(file);
            if (jsonO) {
                const soundDef = jsonO["sound_definitions"];
                if (soundDef) {
                    await this.addSubTags(pi, "Sound definition elements", index, ContentIndex_1.AnnotationCategory.soundDefinitionSource, soundDef, true);
                }
            }
            items.push(pi);
        }
        else if (srPath.indexOf("/sounds/music_definitions.json") >= 0) {
            const pi = new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.info, this.id, JsonFileTagsInfoGeneratorTest.musicDefinition, "Music definitions file", project.getItemByExtendedOrProjectPath(file.storageRelativePath), file.storageRelativePath);
            if (!file.isContentLoaded) {
                await file.loadContent(false);
            }
            const jsonO = StorageUtilities_1.default.getJsonObject(file);
            if (jsonO) {
                await this.addSubTags(pi, "Music definition elements", index, ContentIndex_1.AnnotationCategory.musicDefinitionSource, jsonO, true);
            }
            items.push(pi);
        }
        else if (srPath.indexOf("/sounds.json") >= 0) {
            const pi = new ProjectInfoItem_1.default(IInfoItemData_1.InfoItemType.info, this.id, JsonFileTagsInfoGeneratorTest.sound, "Sounds file", project.getItemByExtendedOrProjectPath(file.storageRelativePath), file.storageRelativePath);
            if (!file.isContentLoaded) {
                await file.loadContent(false);
            }
            const jsonO = StorageUtilities_1.default.getJsonObject(file);
            if (jsonO) {
                const blockSounds = jsonO["block_sounds"];
                if (blockSounds) {
                    await this.addSubTags(pi, "Block sounds", index, ContentIndex_1.AnnotationCategory.blockSounds, blockSounds, true);
                }
                const entitySounds = jsonO["entity_sounds"];
                if (entitySounds) {
                    await this.addSubTags(pi, "Entity sounds", index, ContentIndex_1.AnnotationCategory.entitySounds, entitySounds, true);
                }
                const individualEventSounds = jsonO["individual_event_sounds"];
                if (individualEventSounds) {
                    await this.addSubTags(pi, "Individual sounds", index, ContentIndex_1.AnnotationCategory.individualEventSoundsSource, individualEventSounds);
                }
                const interactiveSounds = jsonO["interactive_sounds"];
                if (interactiveSounds) {
                    await this.addSubTags(pi, "Interactive sounds", index, ContentIndex_1.AnnotationCategory.interactiveSounds, interactiveSounds, true);
                }
            }
            items.push(pi);
        }
    }
    async addSubTags(pi, prefix, index, annotation, rootTag, doNotIncrement) {
        if (!rootTag) {
            return;
        }
        for (const childEltName in rootTag) {
            if (childEltName) {
                let colon = childEltName.indexOf(":");
                const childObj = rootTag[childEltName];
                if (colon <= 0 || childEltName.substring(0, colon) === "minecraft") {
                    if (!doNotIncrement) {
                        pi.incrementFeature(prefix, childEltName);
                    }
                    let bareTag = childEltName;
                    if (colon > 1 && colon < childEltName.length - 2) {
                        bareTag = childEltName.substring(colon + 1);
                    }
                    if (pi.projectItem && pi.projectItem.projectPath) {
                        let packRelativePath = await pi.projectItem.getPackRelativePath();
                        if (packRelativePath) {
                            packRelativePath = StorageUtilities_1.default.getBaseFromName(StorageUtilities_1.default.ensureNotStartsWithDelimiter(packRelativePath));
                            index.insert(bareTag, packRelativePath, annotation);
                        }
                        index.insert(bareTag, pi.projectItem.projectPath, annotation);
                        if (typeof childObj === "number") {
                            if (numericAllowList.includes(bareTag)) {
                                index.insert(bareTag + "==" + Math.round(childObj), pi.projectItem.projectPath, annotation);
                            }
                        }
                        else if (typeof childObj === "boolean") {
                            if (boolAllowList.includes(bareTag)) {
                                index.insert(bareTag + "==" + (childObj ? "t" : "f"), pi.projectItem.projectPath, annotation);
                            }
                        }
                        else if (Array.isArray(childObj)) {
                            index.insert(bareTag + "==a", pi.projectItem.projectPath, annotation);
                            this.addSubTagsForArray(pi, bareTag, index, annotation, childObj);
                        }
                        else if (typeof childObj === "string" && childObj.length > 0) {
                            if (tagAllowList.includes(bareTag)) {
                                index.insert(bareTag + "==" + childObj, pi.projectItem.projectPath, annotation);
                                index.insert(childObj, pi.projectItem.projectPath, annotation);
                            }
                        }
                        else {
                            if (childObj && childObj.constructor !== Array) {
                                this.addDescendentSubTags(pi, bareTag, index, annotation, childObj, childEltName);
                            }
                        }
                    }
                }
            }
        }
    }
    addSubTagsForArray(pi, prefix, index, annotation, rootArr) {
        if (!rootArr) {
            return;
        }
        for (const childObj of rootArr) {
            if (typeof childObj === "string" && childObj.length > 0) {
                if (pi && pi.projectItem && pi.projectItem.projectPath) {
                    index.insert(prefix + "." + childObj, pi.projectItem.projectPath, annotation);
                    index.insert(childObj, pi.projectItem.projectPath, annotation);
                }
            }
            else {
                if (childObj &&
                    typeof childObj !== "number" &&
                    typeof childObj !== "boolean" &&
                    childObj.constructor !== Array) {
                    this.addDescendentSubTags(pi, prefix, index, annotation, childObj);
                }
            }
        }
    }
    addDescendentSubTags(pi, prefix, index, annotation, rootTag, parentName) {
        if (!rootTag) {
            return;
        }
        for (const childEltName in rootTag) {
            if (childEltName) {
                const obj = rootTag[childEltName];
                if (pi.projectItem && pi.projectItem.projectPath) {
                    if (childEltName === "test" && parentName === "filters" && typeof obj === "string") {
                        index.insert(obj, pi.projectItem?.projectPath, ContentIndex_1.AnnotationCategory.entityFilter);
                    }
                    index.insert(prefix + "." + childEltName, pi.projectItem?.projectPath, annotation);
                    let bareTag = childEltName;
                    let colon = childEltName.indexOf(":");
                    if (colon <= 0 || childEltName.substring(0, colon) === "minecraft") {
                        if (colon > 1 && colon < childEltName.length - 2) {
                            bareTag = childEltName.substring(colon + 1);
                        }
                        const inspectTag = parentName && inspectTagList.includes(parentName);
                        if (typeof obj === "number") {
                            if (numericAllowList.includes(bareTag) || inspectTag) {
                                index.insert(prefix + "." + bareTag + "==" + Math.round(obj), pi.projectItem.projectPath, annotation);
                            }
                        }
                        else if (typeof obj === "boolean") {
                            if (boolAllowList.includes(bareTag) || inspectTag) {
                                index.insert(prefix + "." + bareTag + "==" + (obj ? "t" : "f"), pi.projectItem.projectPath, annotation);
                            }
                        }
                        else if (typeof obj === "string") {
                            if (tagAllowList.includes(bareTag) || inspectTag) {
                                index.insert(prefix + "." + bareTag + "==" + obj, pi.projectItem.projectPath, annotation);
                            }
                        }
                        else if (Array.isArray(obj)) {
                            this.addSubTagsForArray(pi, prefix + "." + bareTag, index, annotation, obj);
                        }
                        else {
                            if (obj && obj.constructor !== Array) {
                                this.addDescendentSubTags(pi, prefix + "." + bareTag, index, annotation, obj, childEltName);
                            }
                        }
                    }
                }
            }
        }
    }
}
exports.default = JsonFileTagsInfoGenerator;

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