import { world, system, BlockPermutation, ItemStack } from "@minecraft/server";
import { ActionFormData } from "@minecraft/server-ui"


export class GrinderComponent {
    constructor() {
        this.onTick = this.onTick.bind(this);
        this.onPlayerInteract = this.onPlayerInteract.bind(this);

        this.REDSTONE_POWER_BLOCKS = [
            { id: "minecraft:redstone_wire", state: "redstone_signal" },
            { id: "minecraft:powered_comparator", state: "minecraft:cardinal_direction" },
            { id: "minecraft:powered_repeater", state: "minecraft:cardinal_direction" },
            { id: "minecraft:redstone_torch", state: "torch_facing_direction" },
            { id: "minecraft:observer", state: "minecraft:facing_direction" },
            { id: "minecraft:lever", state: "open_bit" },
            { id: "minecraft:lever", state: "open_bit" },
            { id: "_button", state: "button_pressed_bit" },
            { id: "_pressure_plate", state: "redstone_signal" },
            { id: "minecraft:redstone_block", state: null },
        ];

        this.GRINDER_RECIPES = [

            { ingredient: "minecraft:netherrack", product: "null", bonus: { item: "minecraft:nether_wart", chance: 0.1 } },
            { ingredient: "minecraft:basalt", product: "null", bonus: { item: "minecraft:ancient_debris", chance: 0.001 } },
            { ingredient: "minecraft:blackstone", product: "minecraft:coal", bonus: { item: "minecraft:gilded_blackstone", chance: 0.03 } },
            { ingredient: "minecraft:packed_ice", product: "minecraft:snow", bonus: { item: "minecraft:cod", chance: 0.05 } },
            { ingredient: "minecraft:bone", product: "minecraft:bone_meal", bonus: { item: "minecraft:bone_block", chance: 0.3 } },
            { ingredient: "minecraft:cobblestone", product: "minecraft:gravel", bonus: { item: "null", chance: 1 } },
            { ingredient: "minecraft:cobbled_deepslate", product: "minecraft:gravel", bonus: { item: "minecraft:coal", chance: 0.1 } },
            { ingredient: "minecraft:mossy_cobblestone", product: "minecraft:cobblestone", bonus: { item: "minecraft:moss_block", chance: 0.5 } },
            { ingredient: "minecraft:andesite", product: "minecraft:cobblestone", bonus: { item: "minecraft:suspicious_gravel", chance: 0.1 } },
            { ingredient: "minecraft:deepslate", product: "minecraft:cobbled_deepslate", bonus: { item: "null", chance: 1 } },
            { ingredient: "minecraft:stone", product: "minecraft:cobblestone", bonus: { item: "null", chance: 1 } },
            { ingredient: "minecraft:dripstone_block", product: "minecraft:cobblestone", bonus: { item: "minecraft:raw_iron", chance: 0.1 } },
            { ingredient: "minecraft:tuff", product: "minecraft:cobblestone", bonus: { item: "minecraft:clay_ball", chance: 0.1 } },
            { ingredient: "minecraft:amethyst_block", product: "minecraft:amethyst_shard", bonus: { item: "minecraft:glowstone_dust", chance: 0.25 } },
            { ingredient: "minecraft:gravel", product: "minecraft:sand", bonus: { item: "minecraft:flint", chance: 0.25 } },
            { ingredient: "minecraft:suspicious_gravel", product: "minecraft:sand", bonus: { item: "minecraft:raw_iron", chance: 0.25 } },
            { ingredient: "minecraft:suspicious_sand", product: "minecraft:sand", bonus: { item: "minecraft:brick", chance: 0.25 } },
            { ingredient: "minecraft:diorite", product: "minecraft:cobblestone", bonus: { item: "minecraft:quartz", chance: 0.1 } },
            { ingredient: "minecraft:granite", product: "minecraft:cobblestone", bonus: { item: "minecraft:raw_copper", chance: 0.1 } },
            { ingredient: "minecraft:calcite", product: "minecraft:cobblestone", bonus: { item: "minecraft:bone_meal", chance: 0.1 } },
            { ingredient: "minecraft:red_sandstone", product: "minecraft:red_sand", bonus: { item: "null", chance: 1 } },
            { ingredient: "minecraft:sandstone", product: "minecraft:sand", bonus: { item: "null", chance: 1 } },
            { ingredient: "minecraft:hardened_clay", product: "minecraft:red_sand", bonus: { item: "suspicious_sand", chance: 0.05 } },

        ];

    }

    onPlayerInteract(e) {
        const block = e.block;
        const player = e.player;
        let selectedSlot = player.selectedSlotIndex;
        let handItem = player.getComponent("inventory").container.getItem(selectedSlot);

        if (handItem?.typeId == "pb_red:redstone_wrench") {
            block.dimension.runCommand(`playsound random.click @a ${block.location.x} ${block.location.y} ${block.location.z} 0.5`)

            const grinderInfoUI = new ActionFormData()
                .title("Grinder Recipes")
                .body("§bGrinder Recipes§r\n\n" +
                    "The grinder allows you to process blocks into useful materials. Here's a list of ingredients and their outputs:\n\n" +
                    "§lRecipes:§r\n" +
                    "\n- §bNetherrack§r:\n" +
                    "   Product: None\n" +
                    "   Bonus: Nether Wart (10%%%)\n" +
                    "\n- §bBasalt§r:\n" +
                    "   Product: None\n" +
                    "   Bonus: Ancient Debris (0.1%%)\n" +
                    "\n- §bBlackstone§r:\n" +
                    "   Product: Coal\n" +
                    "   Bonus: Gilded Blackstone (3%%)\n" +
                    "\n- §bPacked Ice§r:\n" +
                    "   Product: Snow\n" +
                    "   Bonus: Cod (5%%)\n" +
                    "\n- §bBone§r:\n" +
                    "   Product: Bone Meal\n" +
                    "   Bonus: Bone Block (30%%)\n" +
                    "\n- §bCobblestone§r:\n" +
                    "   Product: Gravel\n" +
                    "   Bonus: None\n" +
                    "\n- §bCobbled Deepslate§r:\n" +
                    "   Product: Gravel\n" +
                    "   Bonus: Coal (10%%)\n" +
                    "\n- §bMossy Cobblestone§r:\n" +
                    "   Product: Cobblestone\n" +
                    "   Bonus: Moss Block (50%%)\n" +
                    "\n- §bAndesite§r:\n" +
                    "   Product: Cobblestone\n" +
                    "   Bonus: Suspicious Gravel (10%%)\n" +
                    "\n- §bDeepslate§r:\n" +
                    "   Product: Cobbled Deepslate\n" +
                    "   Bonus: None\n" +
                    "\n- §bStone§r:\n" +
                    "   Product: Cobblestone\n" +
                    "   Bonus: None\n" +
                    "\n- §bDripstone Block§r:\n" +
                    "   Product: Cobblestone\n" +
                    "   Bonus: Raw Iron (10%%)\n" +
                    "\n- §bTuff§r:\n" +
                    "   Product: Cobblestone\n" +
                    "   Bonus: Clay Ball (10%%)\n" +
                    "\n- §bAmethyst Block§r:\n" +
                    "   Product: Amethyst Shard\n" +
                    "   Bonus: Glowstone Dust (25%%)\n" +
                    "\n- §bGravel§r:\n" +
                    "   Product: Sand\n" +
                    "   Bonus: Flint (25%%)\n" +
                    "\n- §bSuspicious Gravel§r:\n" +
                    "   Product: Sand\n" +
                    "   Bonus: Raw Iron (25%%)\n" +
                    "\n- §bSuspicious Sand§r:\n" +
                    "   Product: Sand\n" +
                    "   Bonus: Brick (25%%)\n" +
                    "\n- §bDiorite§r:\n" +
                    "   Product: Cobblestone\n" +
                    "   Bonus: Quartz (10%%)\n" +
                    "\n- §bGranite§r:\n" +
                    "   Product: Cobblestone\n" +
                    "   Bonus: Raw Copper (10%%)\n" +
                    "\n- §bCalcite§r:\n" +
                    "   Product: Cobblestone\n" +
                    "   Bonus: Bone Meal (10%%)\n" +
                    "\n- §bRed Sandstone§r:\n" +
                    "   Product: Red Sand\n" +
                    "   Bonus: None\n" +
                    "\n- §bSandstone§r:\n" +
                    "   Product: Sand\n" +
                    "   Bonus: None\n" +
                    "\n- §bTerracotta§r:\n" +
                    "   Product: Red Sand\n" +
                    "   Bonus: Suspicious Sand (5%%)\n\n")
                .button("OK")
                .show(player);

        }
    }

    onTick(e) {
        const block = e.block;
        let direction = block.permutation.getState('minecraft:cardinal_direction');
        const powered = block.permutation.getState('pb_red:working');
        const container = block.above();
        if (!container) return

        if (!this.hasRedstonePower(block, direction)) {
            if (powered) {
                block.setPermutation(block.permutation.withState('pb_red:working', false));
            }
            return
        } else {
            if (!powered) {
                block.setPermutation(block.permutation.withState('pb_red:working', true));
            }
        }

        if (this.isValidContainer(container)) {

            const findRecipeByIngredient = (ingredient) => {
                return (
                    this.GRINDER_RECIPES.find(recipe => recipe.ingredient === ingredient)
                );
            };

            let inventory = container?.getComponent("minecraft:inventory")?.container;
            for (let slot = 0; slot < inventory.size; slot++) {
                let item = inventory.getItem(slot);
                if (!item || findRecipeByIngredient(item.typeId) == undefined) continue;

                system.runTimeout(() => {
                    try {
                        this.crushItem(item, block);
                    } catch { }
                }, 5 + (item.amount * 2))

                this.grinderFX(item.amount, block)

                inventory.setItem(slot, new ItemStack("minecraft:air", 1));

                break;
            }

        }
    }

    grinderFX(amount, block) {
        let nb = amount / 5
        block.dimension.runCommand(`playsound block.grindstone.use @a ${block.location.x} ${block.location.y} ${block.location.z} 0.2`)
        block.dimension.spawnParticle("minecraft:falling_dust_gravel_particle", this.getBlockCenter(block))
        if (amount <= 5) return
        const Launcher = system.runInterval(() => {
            if (nb <= 0) {
                system.clearRun(Launcher);
                return;
            }
            block.dimension.runCommand(`playsound block.grindstone.use @a ${block.location.x} ${block.location.y} ${block.location.z} 0.2`)
            block.dimension.spawnParticle("minecraft:falling_dust_gravel_particle", this.getBlockCenter(block))

            nb--
        }, 10)

    }

    crushItem(item, block) {
        const loc = this.getBlockCenter(block.below());
        const dimension = block.dimension;
        const amount = item.amount

        let recipe = this.GRINDER_RECIPES.find(r => r.ingredient === item.typeId);
        const newId = recipe.product;
        const bonusItem = recipe.bonus.item;
        const bonusChance = recipe.bonus.chance;
        let bonusAmount = 0
        for (let i = 1; i <= amount; i++) {
            if (bonusChance > Math.random()) {
                bonusAmount++
            }
        }

        if (newId !== "null" && amount > 0) {
            dimension.runCommand(`playsound random.pop @a ${loc.x} ${loc.y + 1} ${loc.z}`)
            const newItemEntity = dimension.spawnItem(new ItemStack(newId, amount), loc);
            newItemEntity.teleport({
                x: loc.x,
                y: loc.y,
                z: loc.z,
            })
        }

        if (bonusItem !== "null" && bonusAmount > 0) {
            dimension.runCommand(`playsound random.pop @a ${loc.x} ${loc.y + 1} ${loc.z}`)
            const bonusItemEntity = dimension.spawnItem(new ItemStack(bonusItem, bonusAmount), loc);
            bonusItemEntity.teleport({
                x: loc.x,
                y: loc.y,
                z: loc.z,
            })
        }

    }

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

    getBlockCenter(block) {
        const loc = block.location;
        return { x: loc.x + 0.5, y: loc.y + 0.1, z: loc.z + 0.5 };
    }

    isValidContainer(block) {
        if (!block) return;
        const validContainers = [
            "minecraft:chest",
            "minecraft:hopper",
            "minecraft:barrel",
            "minecraft:dropper",
            "minecraft:dispenser",
            "minecraft:trapped_chest",
            //shulker box
            "minecraft:undyed_shulker_box",
            "minecraft:black_shulker_box",
            "minecraft:blue_shulker_box",
            "minecraft:brown_shulker_box",
            "minecraft:cyan_shulker_box",
            "minecraft:gray_shulker_box",
            "minecraft:green_shulker_box",
            "minecraft:light_blue_shulker_box",
            "minecraft:light_gray_shulker_box",
            "minecraft:lime_shulker_box",
            "minecraft:magenta_shulker_box",
            "minecraft:orange_shulker_box",
            "minecraft:pink_shulker_box",
            "minecraft:purple_shulker_box",
            "minecraft:red_shulker_box",
            "minecraft:white_shulker_box",
            "minecraft:yellow_shulker_box",
        ];
        return validContainers.includes(block.typeId);
    }


    hasRedstonePower(block, direction) {
        const north = block.north();
        const east = block.east();
        const south = block.south();
        const west = block.west();
        const above = block.above();
        const below = block.below();

        const adjacentBlocks = [north, east, south, west, above, below];
        const directionList = ["north", "east", "south", "west", "up", "down"];

        return adjacentBlocks.some((adjacentBlock, index) => {
            if (!adjacentBlock) return false;

            const redstoneBlock = this.REDSTONE_POWER_BLOCKS.find(({ id }) => adjacentBlock.typeId.includes(id));
            if (!redstoneBlock) return false;

            const { id, state } = redstoneBlock;
            if (id === "minecraft:redstone_block") return true;

            if (id === "minecraft:redstone_wire") {
                let redstonePowerState = adjacentBlock.permutation.getState(state);
                return redstonePowerState > 0;
            }

            if (id === "minecraft:powered_comparator" || id === "minecraft:powered_repeater") {
                return adjacentBlock.permutation.getState(state) === directionList[index];
            }

            if (id === "minecraft:redstone_torch") {
                return adjacentBlock.permutation.getState(state) !== this.getOppositeDirection(directionList[index]) && index !== 4;
            }

            if (id === "minecraft:observer") {
                return adjacentBlock.permutation.getState(state) == directionList[index] && adjacentBlock.permutation.getState("powered_bit") == true;
            }

            if (id === "minecraft:lever") {
                return adjacentBlock.permutation.getState(state) == true;
            }

            if (id === "_button") {
                return adjacentBlock.permutation.getState(state) == true;
            }

            if (id === "_pressure_plate") {
                return adjacentBlock.permutation.getState(state) > 0;
            }

            return false;
        });
    }

}