import { world, system, ItemStack, ItemDurabilityComponent, GameMode, ItemEnchantableComponent } from '@minecraft/server';
import { randomNum } from '../math/randomNumbers';
import { BlockManager } from '../block/manager';
import { ItemManager } from '../item/manager';
export class veinminerManager {
    static oreIDs = [
        "minecraft:coal_ore",
        "minecraft:deepslate_coal_ore",
        "minecraft:copper_ore",
        "minecraft:deepslate_copper_ore",
        "minecraft:iron_ore",
        "minecraft:deepslate_iron_ore",
        "minecraft:gold_ore",
        "minecraft:deepslate_gold_ore",
        "minecraft:redstone_ore",
        "minecraft:deepslate_redstone_ore",
        "minecraft:lit_redstone_ore",
        "minecraft:lit_deepslate_redstone_ore",
        "minecraft:lapis_ore",
        "minecraft:deepslate_lapis_ore",
        "minecraft:diamond_ore",
        "minecraft:deepslate_diamond_ore",
        "minecraft:emerald_ore",
        "minecraft:deepslate_emerald_ore",
        "minecraft:nether_gold_ore",
        "minecraft:quartz_ore",
        "minecraft:ancient_debris"
    ];
    static oreData = [
        {
            id: "minecraft:coal_ore",
            level: 1,
            item: "minecraft:coal",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:deepslate_coal_ore",
            level: 1,
            item: "minecraft:coal",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:copper_ore",
            level: 1,
            item: "minecraft:raw_copper",
            itemPerLevel: 5,
            chance: 0.33
        },
        {
            id: "minecraft:deepslate_copper_ore",
            level: 1,
            item: "minecraft:raw_copper",
            itemPerLevel: 5,
            chance: 0.33
        },
        {
            id: "minecraft:iron_ore",
            level: 2,
            item: "minecraft:raw_iron",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:deepslate_iron_ore",
            level: 2,
            item: "minecraft:raw_iron",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:gold_ore",
            level: 3,
            item: "minecraft:raw_gold",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:deepslate_gold_ore",
            level: 3,
            item: "minecraft:raw_gold",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:redstone_ore",
            level: 3,
            item: "minecraft:redstone",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:deepslate_redstone_ore",
            level: 3,
            item: "minecraft:redstone",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:lit_redstone_ore",
            level: 3,
            item: "minecraft:redstone",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:lit_deepslate_redstone_ore",
            level: 3,
            item: "minecraft:redstone",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:lapis_ore",
            level: 2,
            item: "minecraft:lapis_lazuli",
            itemPerLevel: 9,
            chance: 0.33
        },
        {
            id: "minecraft:deepslate_lapis_ore",
            level: 2,
            item: "minecraft:lapis_lazuli",
            itemPerLevel: 9,
            chance: 0.33
        },
        {
            id: "minecraft:diamond_ore",
            level: 3,
            item: "minecraft:diamond",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:deepslate_diamond_ore",
            level: 3,
            item: "minecraft:diamond",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:emerald_ore",
            level: 3,
            item: "minecraft:emerald",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:deepslate_emerald_ore",
            level: 3,
            item: "minecraft:emerald",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:nether_gold_ore",
            level: 2,
            item: "minecraft:gold_nugget",
            itemPerLevel: 6,
            chance: 0.33
        },
        {
            id: "minecraft:quartz_ore",
            level: 2,
            item: "minecraft:quartz",
            itemPerLevel: 1,
            chance: 0.33
        },
        {
            id: "minecraft:ancient_debris",
            level: 4,
            item: "minecraft:ancient_debris",
            itemPerLevel: 0,
            chance: 0
        }
    ];
    static start(player, brokenBlock, item, mainhand) {
        const durComp = item.getComponent(ItemDurabilityComponent.componentId);
        if (!durComp)
            return;
        const enchComp = item.getComponent(ItemEnchantableComponent.componentId);
        let fortuneLevel = undefined;
        let unbreakingLevel = undefined;
        let silkTouched = false;
        if (enchComp) {
            silkTouched = enchComp.hasEnchantment("silk_touch");
            if (enchComp.hasEnchantment("fortune")) {
                fortuneLevel = enchComp.getEnchantment("fortune").level;
            }
            if (enchComp.hasEnchantment("unbreaking")) {
                unbreakingLevel = enchComp.getEnchantment("unbreaking").level;
            }
        }
        const blockData = this.oreData.find((f) => f.id == brokenBlock.typeId);
        if (!blockData)
            return;
        if (this.getPickaxeLevel(item) < blockData.level)
            return;
        this.getBlocks(brokenBlock, player, item, mainhand, durComp, blockData, fortuneLevel, unbreakingLevel, silkTouched);
    }
    static getPickaxeLevel(item) {
        let level = 5;
        switch (item.typeId) {
            case "minecraft:wooden_pickaxe":
                level = 1;
                break;
            case "minecraft:golden_pickaxe":
                level = 1;
                break;
            case "minecraft:stone_pickaxe":
                level = 2;
                break;
            case "minecraft:iron_pickaxe":
                level = 3;
                break;
            case "minecraft:diamond_pickaxe":
                level = 4;
                break;
            case "minecraft:netherite_pickaxe":
                level = 5;
                break;
        }
        return level;
    }
    static limit = 64;
    static getBlocks(block, source, item, mainhand, durComp, oreData, fortune, unbreakingLevel, silkTouched) {
        let durability = durComp.damage;
        let blockNum = 0;
        let stop = false;
        const deniedLocs = [];
        function tick(block, takeDur, fortunable, breakBlock) {
            deniedLocs.push(block.location);
            if (blockNum >= veinminerManager.limit)
                return;
            if (stop == true)
                return;
            const sameID = block.typeId;
            const blocks = BlockManager.getBlocksAround(block);
            if (breakBlock)
                veinminerManager.break(block, fortune, oreData, fortunable, silkTouched);
            if (takeDur == true && ItemManager.reduceDurability(unbreakingLevel)) {
                durability = durability + 1;
                if (durability >= durComp.maxDurability) {
                    stop = true;
                    return;
                }
            }
            for (const newblock of blocks) {
                if (newblock != undefined) {
                    const newloc = newblock.location;
                    if ((newblock.typeId == sameID || (sameID.includes('redstone_ore') && newblock.typeId.includes('redstone_ore'))) && !veinminerManager.isDenied(newloc, deniedLocs)) {
                        blockNum = blockNum + 1;
                        if (source.getGameMode() != GameMode.creative) {
                            tick(newblock, true, true, true);
                        }
                        else {
                            tick(newblock, false, true, true);
                        }
                    }
                }
            }
        }
        tick(block, true, false, false);
        if (durability >= durComp.maxDurability) {
            stop = true;
            system.runTimeout(() => {
                source.dimension.playSound("random.break", source.location);
                mainhand.setItem(undefined);
            });
            return;
        }
        else {
            system.runTimeout(() => {
                durComp.damage = durability;
                mainhand.setItem(item);
            });
        }
    }
    static isDenied(blockLoc, deniedList) {
        let isDenied = false;
        for (const loc of deniedList) {
            if (blockLoc.x == loc.x && blockLoc.y == loc.y && blockLoc.z == loc.z)
                isDenied = true;
        }
        return isDenied;
    }
    static break(block, fortune, oreData, fortunable, silkTouched) {
        let typeId = block.typeId;
        if (typeId.includes("lit_")) {
            typeId = typeId.replace("lit_", "");
        }
        const { x, y, z } = block.location;
        const center = block.center();
        system.runTimeout(() => {
            if (silkTouched) {
                const lastRule = world.gameRules.doTileDrops;
                world.gameRules.doTileDrops = false;
                BlockManager.destroyBlock(block.dimension, block.location);
                world.gameRules.doTileDrops = lastRule;
                const item = new ItemStack(typeId, 1);
                const itemEntity = ItemManager.spawnItem(item, block.dimension, {
                    x: center.x,
                    y: center.y - 0.4,
                    z: center.z,
                });
                itemEntity?.applyImpulse({
                    x: randomNum(-0.1, 0.1),
                    y: randomNum(0.1, 0.25),
                    z: randomNum(-0.1, 0.1),
                });
            }
            else {
                if (fortune != undefined && fortunable) {
                    const extra = this.calculateExtraItems(oreData.itemPerLevel, oreData.chance, fortune);
                    if (extra > 0) {
                        const center = block.center();
                        const item = new ItemStack(oreData.item, extra);
                        const itemEntity = ItemManager.spawnItem(item, block.dimension, { x: center.x, y: center.y - 0.4, z: center.z });
                        itemEntity?.applyImpulse({ x: randomNum(-0.1, 0.1), y: randomNum(0.1, 0.25), z: randomNum(-0.1, 0.1) });
                    }
                }
                BlockManager.destroyBlock(block.dimension, block.location);
            }
        });
    }
    static calculateExtraItems(itemsPerLevel, chance, fortuneLevel) {
        let extra = 0;
        for (let i = 0; i < fortuneLevel; i++) {
            for (let i = 0; i < itemsPerLevel; i++) {
                const num = randomNum(0, 1);
                if (num <= chance) {
                    extra = extra + 1;
                }
            }
        }
        return extra;
    }
}
