import {system, world} from "@minecraft/server"
import {getScore} from "cubc/mo_en/armor"
import {plants} from "cubc/mo_en/plants"

export function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

function handleHoe(event, block) {
    let {x: x, y: y, z: z} = block.location;
    const dimension = event.dimension;
    const replanterScore = getScore(event.player, "replanter");
    if (replanterScore > 0) {
        for (const replant of plants) {
            const permutationMatches = block.permutation.matches(`minecraft:${replant["name"]}`);
            if (permutationMatches && block.permutation.getState(replant["growthName"]) === replant["growthNumber"]) {
                system.run(() => {
                    dimension.runCommand(`setblock ${x} ${y} ${z} ${replant["name"]} destroy`);
                    dimension.runCommand(`particle minecraft:crop_growth_emitter ${x} ${y} ${z}`);
                });
            }
        }
    }
}

function handleAxe(event, x, y, z) {
    const treeFellerScore = getScore(event.player, "tree_feller");
    if (treeFellerScore > 0) {
        event.player.runCommand(`execute positioned ${x} ${y} ${z} run function cubc/mo_en/apply_enchants/tool/tree_feller/mine`);
    }
}

function handleShovel(event, x, y, z) {
    const luckyFindScore = getScore(event.player, "lucky_find");
    if (luckyFindScore > 0 && Math.random() < 0.0075 * luckyFindScore) {
        event.player.runCommand(`loot spawn ${x} ${y} ${z} loot "cubc/mo_en/tools/random_ore"`);
    }
}

function handlePickaxe(event, x, y, z) {
    const autoSmeltScore = getScore(event.player, "auto_smelt");
    if (autoSmeltScore > 0) {
        event.player.runCommand(`execute positioned ${x} ${y} ${z} run function cubc/mo_en/apply_enchants/tool/auto_smelt/smelt`);
    }

    const applyEffect = Math.random() < 0.3;
    if (!applyEffect) {
        return;
    }
    const effectIndex = getRandomInt(1, 2);

    switch (effectIndex) {
        case 1:
            // Blast mine
            const blastMineScore = getScore(event.player, "blast_mine");
            if (blastMineScore > 0) {
                destroyBlocksInRadius(event.player.dimension, {x: x, y: y, z: z}, Math.ceil(blastMineScore / 2));
                event.player.runCommand(`particle minecraft:huge_explosion_emitter ${x} ${y} ${z}`);
            }
            break;
        case 2:
            // Block mine
            const blockMineScore = getScore(event.player, "block_mine");
            const r = 1 + blockMineScore;
            if (blockMineScore > 0) {
                event.player.runCommand(`fill ${x - r / 2} ${y - r / 2} ${z - r / 2} ${x + r / 2} ${y + r / 2} ${z + r / 2} air destroy`);
            }
            break;
        default:
            break;
    }
}

function destroyBlocksInRadius(dimension, center, radius) {
    const minX = Math.floor(center.x - radius);
    const minY = Math.floor(center.y - radius);
    const minZ = Math.floor(center.z - radius);
    const maxX = Math.ceil(center.x + radius);
    const maxY = Math.ceil(center.y + radius);
    const maxZ = Math.ceil(center.z + radius);

    for (let x = minX; x <= maxX; x++) {
        for (let y = minY; y <= maxY; y++) {
            for (let z = minZ; z <= maxZ; z++) {
                const distanceSquared = (x - center.x) ** 2 + (y - center.y) ** 2 + (z - center.z) ** 2;
                if (distanceSquared <= radius ** 2) {
                    const block = dimension.getBlock({x, y, z});
                    if (block && !block.permutation.matches("minecraft:air")) {
                        dimension.runCommand(`setblock ${x} ${y} ${z} air destroy`);
                    }

                }
            }
        }
    }
}


world.beforeEvents.playerBreakBlock.subscribe((event) => {
    const block = event.block;
    let {x: x, y: y, z: z} = block.location;

    // Handle Hoe
    handleHoe(event, block);
});

world.afterEvents.playerBreakBlock.subscribe((event) => {
    const block = event.block;
    let {x: x, y: y, z: z} = block.location;

    // 5%, 10%, 15% to give xp on mining a block
    const xpBoostScore = getScore(event.player, "xp_boost");
    if (xpBoostScore > 0 && Math.random() < 0.05 * xpBoostScore) {
        event.player.runCommand(`summon xp_orb ${x} ${y} ${z}`);
    }

    // Handle tools
    handleAxe(event, x, y, z);
    handleShovel(event, x, y, z);
    handlePickaxe(event, x, y, z);
});

export function decrementDurabilityInHand(player) {
    const equipment = player.getComponent('equippable');
    const playerContainer = player?.getComponent("minecraft:inventory").container;
    const item = equipment.getEquipment('Mainhand');
    system.run(() => {
        console.info("DEC");
        if (!item) {
            return;
        }
        const durability = item.getComponent("minecraft:durability");
        if (durability) {
            if (durability.damage >= durability.maxDurability) {
                player.runCommand("replaceitem entity @s slot.weapon.mainhand 0 air");
                world.playSound("random.break", player.location);
            } else {
                durability.damage++;
                playerContainer.setItem(player.selectedSlotIndex, item);
            }
        }
    });
}

system.afterEvents.scriptEventReceive.subscribe((event) => {
    const {id, message, sourceEntity, sourceType} = event;
    if (id === "cubc_mo_en:decrement_durability") {
        decrementDurabilityInHand(sourceEntity);
    }
});