import { MinecraftDimensionTypes, system, world } from "@minecraft/server";
import { ActionFormData } from "@minecraft/server-ui";
import { HexEncoder, Buttons, formatNumberWithHash, replaceNonSpaceChars } from "../utils/my_API";
import { PlayerDynamicProperty } from "../utils/customPlayer";
import config from "nps_mot/config";
import { OrePlacementCollection, OreRarity } from "nps_mot/nps_mot/regionUtils";
import { OreLootCollection } from "./definitions";
world.beforeEvents.itemUse.subscribe(event => {
    handleCodexUse(event);
});
function handleCodexUse(event) {
    if (event.itemStack.typeId !== "nps_mot:codex") {
        return;
    }
    system.run(() => {
        openMainMenu(event.source);
    });
}
function openMainMenu(player) {
    const mainMenuForm = new ActionFormData();
    mainMenuForm.title({ translate: `item.nps_mot:codex` });
    mainMenuForm.body({ translate: `nps_mot:form_body.select_option` });
    const CODE1 = player.getDynamicProperty(PlayerDynamicProperty.CODE1);
    const discoveredObject = HexEncoder.countSetBits(CODE1);
    const objectToDiscover = Codex.oreCodex.length;
    const text = {
        translate: "nps_mot:gap_form_text",
        with: {
            rawtext: [
                { translate: `nps_mot:ore_codex.title` },
                { text: `\n(${discoveredObject}/${objectToDiscover}` }, { text: ' ' },
                { translate: `nps_mot:ore_codex_entry.discovered` },
                { text: `)` },
            ]
        }
    };
    mainMenuForm.button(text, "textures/nps/mot/ui/icon_black_opal_ore");
    mainMenuForm.button(Buttons.close.rawtext, Buttons.close.iconPath);
    mainMenuForm.show(player).then((response) => {
        if (response.canceled) {
            return;
        }
        ;
        switch (response.selection) {
            case 0: {
                openOreCodex(player);
                break;
            }
        }
    });
}
function openOreCodex(player) {
    const form = new ActionFormData()
        .title({ translate: `nps_mot:ore_codex.title` })
        .body({ translate: `nps_mot:form_body.select_option` })
        .button({ translate: `nps_mot:ore_codex.wiki_button` }, 'textures/nps/mot/ui/icon_question')
        .button({ translate: `nps_mot:ore_codex.page_1_to_39` }, Buttons.codex.iconPath)
        .button(Buttons.back.rawtext, Buttons.back.iconPath);
    form.show(player).then(response => {
        if (response.canceled)
            return;
        switch (response.selection) {
            case 0: {
                showOreCodexInfoForm(player);
                break;
            }
            case 1: {
                showPages(player, 1, 39);
                break;
            }
            case 2: {
                openMainMenu(player);
                break;
            }
        }
    });
}
function showOreCodexInfoForm(player) {
    const form = new ActionFormData()
        .title({ translate: `nps_mot:ore_codex.title` });
    const bodyText = {
        translate: "nps_mot:gap_form_text",
        with: {
            rawtext: [
                { translate: `nps_mot:ore_codex.wiki_body.1` }, { text: `\n\n` },
                { translate: `nps_mot:ore_codex.wiki_body.2` }, { text: `\n\n` },
                { translate: `nps_mot:ore_codex.wiki_body.3` }
            ]
        }
    };
    form.body(bodyText)
        .button(Buttons.back.rawtext, Buttons.back.iconPath);
    form.show(player).then(response => {
        if (response.canceled) {
            return;
        }
        switch (response.selection) {
            case 0: {
                openOreCodex(player);
                break;
            }
        }
    });
}
function showPages(player, startPage, endPage) {
    const CODE1 = player.getDynamicProperty(PlayerDynamicProperty.CODE1);
    const form = new ActionFormData()
        .title({ translate: `nps_mot:ore_codex.title` })
        .body({ translate: `nps_mot:form_body.choose_object` });
    const codexEntries = Codex.getEntries(startPage - 1, endPage - 1);
    codexEntries.forEach((entry, index) => {
        const number = formatNumberWithHash(index + 1);
        const name = entry.objectId.split('nps_mot:')[1];
        const discovered = HexEncoder.getBit(CODE1, entry.encodingPosition);
        let dropType = "item";
        const tileList = [
            "nps_mot:tungsten_ore",
            "nps_mot:titanium_ore"
        ];
        if (tileList.includes(entry.objectId)) {
            dropType = "tile";
        }
        if (discovered == false) {
            const hiddenName = replaceNonSpaceChars(name);
            if (dropType == "item") {
                const iconPath = `textures/nps/mot/items/masked/masked_${name}`;
                form.button(`${number}\n${hiddenName}`, iconPath);
            }
            else {
                const iconPath = `textures/nps/mot/blocks/masked/masked_${name}`;
                form.button(`${number}\n${hiddenName}`, iconPath);
            }
        }
        else {
            if (dropType == "item") {
                const text = {
                    translate: "nps_mot:gap_form_text",
                    with: {
                        rawtext: [
                            { text: `${number}\n` },
                            { translate: `item.${entry.objectId}` }
                        ]
                    }
                };
                const iconPath = `textures/nps/mot/items/${name}`;
                form.button(text, iconPath);
            }
            else {
                const text = {
                    translate: "nps_mot:gap_form_text",
                    with: {
                        rawtext: [
                            { text: `${number}\n` },
                            { translate: `tile.${entry.objectId}.name` }
                        ]
                    }
                };
                const iconPath = `textures/nps/mot/blocks/${name}`;
                form.button(text, iconPath);
            }
        }
    });
    form.button(Buttons.back.rawtext, Buttons.back.iconPath);
    form.show(player).then(response => {
        if (response.canceled)
            return;
        if (response.selection === undefined)
            return;
        if (response.selection == codexEntries.length) {
            //back
            openOreCodex(player);
        }
        else {
            const index = response.selection + startPage - 1;
            const oreCodexEntry = Codex.oreCodex[index];
            showOreCodexEntry(oreCodexEntry, player);
        }
    });
}
function showOreCodexEntry(oreCodexEntry, player) {
    const form = new ActionFormData();
    form.title({ translate: `nps_mot:ore_codex.title` });
    //oreLoot
    const oreLootIndex = OreLootCollection.findOreIndexByOreDrop(oreCodexEntry.objectId);
    if (oreLootIndex === -1)
        return;
    const oreLoot = OreLootCollection.ores[oreLootIndex];
    let oreId = oreLoot.typeId;
    const isDeepslateOre = oreId.includes('deepslate_');
    if (isDeepslateOre) {
        if (oreId != 'nps_mot:deepslate_osmium_ore') {
            oreId = 'nps_mot:'.concat(oreLoot.typeId.split('deepslate_')[1]);
        }
    }
    //orePlacement
    const orePlacementIndex = OrePlacementCollection.findIndexByOreId(oreId);
    if (orePlacementIndex === -1)
        return;
    const orePlacement = OrePlacementCollection.ores[orePlacementIndex];
    const CODE1 = player.getDynamicProperty(PlayerDynamicProperty.CODE1);
    const discovered = HexEncoder.getBit(CODE1, oreCodexEntry.encodingPosition);
    if (discovered == false) {
        const bodyText = {
            translate: "nps_mot:ore_codex_entry.body",
            with: {
                rawtext: [
                    { translate: "nps_mot:use_magnifying_glass_to_scan" }, { text: "\n" },
                    { text: "\n" }, { translate: "nps_mot:ore_codex_entry.name" }, { text: " ???" },
                    { text: "\n" }, { translate: "nps_mot:ore_codex_entry.description" }, { text: " ???" },
                    { text: "\n\n" }, { translate: "nps_mot:ore_codex_entry.ore_category" }, { text: ` ???` },
                    { text: "\n" }, { translate: "nps_mot:ore_codex_entry.dimensions" }, { text: ` ???` },
                    { text: "\n" }, { translate: "nps_mot:ore_codex_entry.rarity" }, { text: ` ???` },
                    { text: "\n" }, { translate: "nps_mot:ore_codex_entry.depth_interval" }, { text: ` ??? ` }, { translate: 'nps_mot:ore_codex_entry.depthInterval.to' }, { text: ` ???` },
                    { text: "\n" }, { translate: "nps_mot:ore_codex_entry.optimumMiningLayer" }, { text: ` ???` },
                    { text: "\n" }, { translate: "nps_mot:ore_codex_entry.fortunable" }, { text: ` ???` },
                    { text: "\n\n" }, { translate: "nps_mot:ore_codex_entry.utility" }, { text: " ???" },
                    { text: "\n\n" }, { translate: "nps_mot:ore_codex_entry.lithotherapy" }, { text: " ???" },
                    { text: "\n\n" }, { translate: "nps_mot:ore_codex_entry.mohs" }, { text: ` ???` }, { text: " - " }, { translate: "nps_mot:ore_codex_entry.hv" }, { text: ` ???` },
                    { text: "\n\n" }, { translate: "nps_mot:ore_codex_entry.canBeFoundIn" }
                ]
            }
        };
        form.body(bodyText);
    }
    else {
        const objectId = oreCodexEntry.objectId.split('nps_mot:')[1];
        let name = undefined;
        if (oreLoot.getLootType() == "item") {
            name = `item.${oreCodexEntry.objectId}`;
        }
        else {
            name = `tile.${oreCodexEntry.objectId}.name`;
        }
        const optimumMiningLayer = orePlacement.density.getOptimalY();
        let optimalMiningLayerText = undefined;
        if (optimumMiningLayer.length == 0) {
            optimalMiningLayerText = { translate: "nps_mot:ore_codex_entry.noOptimalY" };
        }
        else {
            optimalMiningLayerText = { text: orePlacement.density.getOptimalY().join(', ') };
        }
        const oreCategory = oreCodexEntry.oreCategory;
        let dimension = undefined;
        switch (orePlacement.allowedDimension) {
            case MinecraftDimensionTypes.overworld: {
                dimension = "Overworld";
                break;
            }
            case MinecraftDimensionTypes.nether: {
                dimension = "Nether";
                break;
            }
            case MinecraftDimensionTypes.theEnd: {
                dimension = "End";
                break;
            }
        }
        const fortunable = oreLoot.fortuneBoostEnabled == true ? "nps_mot:ore_codex_entry.yes" : "nps_mot:ore_codex_entry.no";
        let rarity = undefined;
        switch (orePlacement.rarity) {
            case OreRarity.VERY_COMMON: {
                rarity = "nps_mot:rarity.very_common";
                break;
            }
            case OreRarity.COMMON: {
                rarity = "nps_mot:rarity.common";
                break;
            }
            case OreRarity.UNCOMMON: {
                rarity = "nps_mot:rarity.uncommon";
                break;
            }
            case OreRarity.RARE: {
                rarity = "nps_mot:rarity.rare";
                break;
            }
            case OreRarity.VERY_RARE: {
                rarity = "nps_mot:rarity.very_rare";
                break;
            }
        }
        const bodyText = {
            translate: "nps_mot:ore_codex_entry.body",
            with: {
                rawtext: [
                    { translate: "nps_mot:ore_codex_entry.name" }, { text: " " }, { translate: name },
                    { text: "\n" }, { translate: "nps_mot:ore_codex_entry.description" }, { text: " " }, { translate: `nps_mot:ore_codex_entry.${objectId}.description` },
                    { text: "\n\n" }, { translate: "nps_mot:ore_codex_entry.ore_category" }, { text: ` ${oreCategory}` },
                    { text: "\n" }, { translate: "nps_mot:ore_codex_entry.dimensions" }, { text: ` ${dimension}` },
                    { text: "\n" }, { translate: "nps_mot:ore_codex_entry.rarity" }, { text: " " }, { translate: rarity },
                    { text: "\n" }, { translate: "nps_mot:ore_codex_entry.depth_interval" }, { text: ` ${orePlacement.density.getDepthInterval()[0]} ` }, { translate: 'nps_mot:ore_codex_entry.depthInterval.to' }, { text: ` ${orePlacement.density.getDepthInterval()[1]}` },
                    { text: "\n" }, { translate: "nps_mot:ore_codex_entry.optimumMiningLayer" }, { text: " " }, optimalMiningLayerText,
                    { text: "\n" }, { translate: "nps_mot:ore_codex_entry.fortunable" }, { text: " " }, { translate: fortunable },
                    { text: "\n\n" }, { translate: "nps_mot:ore_codex_entry.utility" }, { text: " " }, { translate: `nps_mot:ore_codex_entry.${objectId}.utility` },
                    { text: "\n\n" }, { translate: "nps_mot:ore_codex_entry.lithotherapy" }, { text: " " }, { translate: `nps_mot:ore_codex_entry.${objectId}.lithotherapy` },
                    { text: "\n\n" }, { translate: "nps_mot:ore_codex_entry.mohs" }, { text: " " }, { translate: `nps_mot:ore_codex_entry.${objectId}.mohs` }, { text: " - " }, { translate: "nps_mot:ore_codex_entry.hv" }, { text: " " }, { translate: `nps_mot:ore_codex_entry.${objectId}.hv` },
                    { text: "\n\n" }, { translate: "nps_mot:ore_codex_entry.canBeFoundIn" }
                ]
            }
        };
        form.body(bodyText);
    }
    const sources = OreLootCollection.ores.filter((ore) => ore.oreDrop.typeId === oreCodexEntry.objectId);
    if (discovered) {
        sources.forEach(source => {
            const sourceText = { translate: `tile.${source.typeId}.name` };
            const sourceIconPath = `textures/nps/mot/blocks/${source.typeId.split('nps_mot:')[1]}`;
            form.button(sourceText, sourceIconPath);
        });
    }
    else {
        sources.forEach(source => {
            const sourceText = replaceNonSpaceChars(source.typeId.split('nps_mot:')[1]);
            const sourceIconPath = `textures/nps/mot/ui/icon_question`;
            form.button(sourceText, sourceIconPath);
        });
    }
    form.button(Buttons.back.rawtext, Buttons.back.iconPath);
    form.show(player).then(response => {
        if (response.canceled)
            return;
        switch (response.selection) {
            case sources.length: {
                openOreCodex(player);
                break;
            }
        }
    });
}
class CodexEntry {
    constructor(objectId, encodingPosition, oreCategory) {
        this.objectId = objectId;
        this.encodingPosition = encodingPosition;
        this.oreCategory = oreCategory;
    }
}
export class Codex {
    static onOreDiscovery(player) {
        const message = {
            translate: "nps_mot:gap_form_text",
            with: {
                rawtext: [
                    { text: `${config.addonPrefix}` }, { translate: 'nps_mot:ore_codex.new_entry_found.1' }, { text: "\n" },
                    { text: `${config.addonPrefix}` }, { translate: 'nps_mot:ore_codex.new_entry_found.2' }, { text: "\n" },
                    { text: `${config.addonPrefix}` }, { translate: 'nps_mot:ore_codex.new_entry_found.3' }
                ]
            }
        };
        player.sendMessage(message);
        const soundId = 'nps_mot:sparkle_1';
        system.run(() => {
            player.playSound(soundId, { location: player.location });
        });
    }
    static onCompleteOreCodexDiscovery(player) {
        const message = {
            translate: "nps_mot:gap_form_text",
            with: {
                rawtext: [
                    { text: `${config.addonPrefix}` }, { translate: 'nps_mot:ore_codex.complete_discovery.1' }, { text: "\n" },
                    { text: `${config.addonPrefix}` }, { translate: 'nps_mot:ore_codex.complete_discovery.2' }, { text: "\n" },
                    { text: `${config.addonPrefix}` }, { translate: 'nps_mot:ore_codex.complete_discovery.3' }
                ]
            }
        };
        player.sendMessage(message);
        const soundId = 'nps_mot:sparkle_2';
        system.run(() => {
            player.playSound(soundId, { location: player.location });
        });
    }
    static getEncodingPosition(identifier) {
        const entry = this.oreCodex.find(entry => entry.objectId === identifier);
        return entry ? entry.encodingPosition : undefined;
    }
    static getEntries(startEntry, endEntry) {
        return this.oreCodex.slice(startEntry, endEntry + 1);
    }
}
Codex.oreCodex = [
    //...
    new CodexEntry("nps_mot:raw_aluminium", 0, 1), //1
    new CodexEntry("nps_mot:raw_cassiterite", 1, 1), //2
    new CodexEntry("nps_mot:raw_chrome", 2, 1), //3
    new CodexEntry("nps_mot:raw_lead", 3, 1), //4
    new CodexEntry("nps_mot:raw_nickel", 4, 1), //5
    //...
    new CodexEntry("nps_mot:amber", 5, 2), //6
    new CodexEntry("nps_mot:blue_garnet", 6, 2), //7
    new CodexEntry("nps_mot:citrine", 7, 2), //8
    new CodexEntry("nps_mot:topaz", 8, 2), //9
    new CodexEntry("nps_mot:opal", 9, 2), //10
    new CodexEntry("nps_mot:raw_cobalt", 10, 2), //11
    //
    new CodexEntry("nps_mot:peridot", 11, 2), //12
    new CodexEntry("nps_mot:sulfur", 12, 2), //13
    //...
    new CodexEntry("nps_mot:benitoite", 13, 3), //14
    new CodexEntry("nps_mot:fire_opal", 14, 3), //15
    new CodexEntry("nps_mot:garnet", 15, 3), //16
    new CodexEntry("nps_mot:lazurite", 16, 3), //17
    new CodexEntry("nps_mot:spinel", 17, 3), //18
    //...
    new CodexEntry("nps_mot:raw_iridium", 18, 4), //19
    new CodexEntry("nps_mot:raw_palladium", 19, 4), //20
    new CodexEntry("nps_mot:raw_platinum", 20, 4), //21
    new CodexEntry("nps_mot:raw_rhodium", 21, 4), //22
    new CodexEntry("nps_mot:raw_ruthenium", 22, 4), //23
    new CodexEntry("nps_mot:titanium_ore", 23, 4), //24
    //...
    new CodexEntry("nps_mot:tungsten_ore", 24, 5), //25
    new CodexEntry("nps_mot:black_opal", 25, 5), //26
    new CodexEntry("nps_mot:sapphire", 26, 5), //27
    new CodexEntry("nps_mot:ruby", 27, 5), //28
    //...
    new CodexEntry("nps_mot:raw_orichalc", 28, 6), //29
    new CodexEntry("nps_mot:black_diamond", 29, 6), //30
    new CodexEntry("nps_mot:green_diamond", 30, 6), //31
    new CodexEntry("nps_mot:orange_diamond", 31, 6), //32
    new CodexEntry("nps_mot:pink_diamond", 32, 6), //33
    new CodexEntry("nps_mot:purple_diamond", 33, 6), //34
    new CodexEntry("nps_mot:red_diamond", 34, 6), //35
    new CodexEntry("nps_mot:yellow_diamond", 35, 6), //36
    //...
    new CodexEntry("nps_mot:raw_osmium", 36, 7), //37
    //
    new CodexEntry("nps_mot:raw_adamantite", 37, 7), //38
    new CodexEntry("nps_mot:bismuthinite", 38, 7), //39
    //...
];
