import { showArea } from './particle_area_marker.js'
import { world, MolangVariableMap } from "@minecraft/server"


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

        this.seedsBlock = [
            "minecraft:wheat", "minecraft:carrots", "minecraft:potatoes",
            "minecraft:beetroot", "minecraft:pumpkin_stem", "minecraft:melon_stem",
            "minecraft:torchflower_crop", "minecraft:pitcher_crop"
        ];

        this.saplingBlock = [
            "minecraft:acacia_sapling",
            "minecraft:birch_sapling",
            "minecraft:cherry_sapling",
            "minecraft:jungle_sapling",
            "minecraft:oak_sapling",
            "minecraft:dark_oak_sapling",
            "minecraft:pale_oak_sapling",
            "minecraft:spruce_sapling",
            "minecraft:mangrove_propagule",
        ]


    }

    onPlayerInteract(e) {
        const block = e.block;
        const player = e.player;

        let selectedSlot = player.selectedSlotIndex;
        let handItem = player.getComponent("inventory").container.getItem(selectedSlot);

        const currentLevel = block.permutation.getState('pb_red:level') || 0;

        let requiredItems = 0;
        if (currentLevel === 1) {
            requiredItems = 16;
        } else if (currentLevel === 2) {
            requiredItems = 32;
        }

        if (handItem?.typeId === "minecraft:bone_block") {
            if (currentLevel >= 3) {
                player.runCommand(`tellraw @s {"rawtext":[{"text":"§cThe Fertilizer is already at maximum level!"}]}`);
                return;
            }

            if (handItem.amount >= requiredItems) {

                block.setPermutation(block.permutation.withState('pb_red:level', currentLevel + 1));
                player.runCommand(`clear @s minecraft:bone_block 0 ${requiredItems}`);
                player.runCommand(`tellraw @s {"rawtext":[{"text":"§aThe Fertilizer level has been upgraded to §e${currentLevel + 1}§a!"}]}`);
                block.dimension.runCommand(`playsound random.levelup @a ${block.location.x} ${block.location.y} ${block.location.z}`);
            } else {
                player.runCommand(`tellraw @s {"rawtext":[{"text":"§cYou need at least §e${requiredItems}§c bone blocks to upgrade the Fertilizer!"}]}`);
            }
        } else if (handItem?.typeId === "pb_red:redstone_wrench") {
            const showParticle = block.permutation.getState('pb_red:particle');
            block.setPermutation(block.permutation.withState('pb_red:particle', !showParticle));
            block.dimension.runCommand(`playsound random.click @a ${block.location.x} ${block.location.y} ${block.location.z}`);

        } else {
            player.runCommand(`tellraw @s {"rawtext":[{"text":"§cYou must hold bone blocks to upgrade the Fertilizer level!"}]}`);
        }
    }


    onTick(e) {
        const { block } = e;
        const center = this.getBlockCenter(block)
        if (!this.isFertilizerBlock(block)) return
        const currentLevel = block.permutation.getState('pb_red:level') || 0;
        const showParticle = block.permutation.getState('pb_red:particle');

        const level_size = [
            3, 4, 5
        ]
        const areaSize = level_size[currentLevel - 1]

        if (showParticle)
            spawnAreaParticle(center, block.dimension, 3, areaSize)

        let containerBlock = block.above()
        if (!containerBlock) return

        if (!this.isValidContainer(containerBlock)) {
            containerBlock = block.below()
            if (!this.isValidContainer(containerBlock)) return;
        };
        let container = containerBlock?.getComponent("minecraft:inventory")?.container;
        if (!this.checkAndRemoveItems(container, "minecraft:bone_meal", 1, false)) return

        const blockList = this.getBlocksInSquare(center, areaSize, block.dimension)

        for (const squareBlock of blockList) {
            const below = squareBlock.below()

            if (this.seedsBlock.includes(squareBlock.typeId)) {
                this.growCrop(block, container, squareBlock)

            } else if (this.saplingBlock.includes(squareBlock.typeId)) {
                // -> if sappling set random struct (3 per type) -> one shot grow mais use bcp de bone meal -> work with pale tree + work with 4X spruce
                this.growTree(block, container, squareBlock)

            } else if (squareBlock.typeId == "minecraft:cactus") {
                this.growCrop(block, container, squareBlock)

            } else if (squareBlock.typeId == "minecraft:air" && below.typeId == "minecraft:grass_block") {
                this.growGrass(block, container, squareBlock, "grass")

            } else if (squareBlock.typeId == "minecraft:air" && below.typeId == "minecraft:moss_block") {
                this.growGrass(block, container, squareBlock, "moss")

            } else if (squareBlock.typeId == "minecraft:air" && below.typeId == "minecraft:pale_moss_block") {
                this.growGrass(block, container, squareBlock, "pale_moss")

            }
        }

    }

    growCrop(block, container, squareBlock) {
        if (squareBlock.typeId == "minecraft:cactus" && squareBlock.above().isAir) {
            if (this.checkAndRemoveItems(container, "minecraft:bone_meal", this.getRandomInt(1, 3), true)) {
                this.growParticle(squareBlock.above())
                squareBlock.above().setType("minecraft:cactus")
            }
        } else if (squareBlock.typeId == "minecraft:pitcher_crop") {
            const growLlv = squareBlock.permutation.getState("growth")
            if (growLlv < 4) {
                if (this.checkAndRemoveItems(container, "minecraft:bone_meal", 1, true)) {
                    this.growParticle(squareBlock)
                    squareBlock.setPermutation(squareBlock.permutation.withState("growth", growLlv + 1))
                    if (growLlv > 1)
                        squareBlock.above().setPermutation(squareBlock.permutation.withState("growth", growLlv + 1).withState("upper_block_bit", true))
                }
            }

        } else if (squareBlock.typeId == "minecraft:torchflower_crop") {
            const growLlv = squareBlock.permutation.getState("growth")
            if (growLlv < 1) {
                if (this.checkAndRemoveItems(container, "minecraft:bone_meal", 1, true)) {
                    this.growParticle(squareBlock)
                    squareBlock.setPermutation(squareBlock.permutation.withState("growth", growLlv + 1))
                }
            } else {
                squareBlock.setType("minecraft:torchflower")
            }

        } else {
            const growLlv = squareBlock.permutation.getState("growth")
            if (growLlv < 7) {
                if (this.checkAndRemoveItems(container, "minecraft:bone_meal", this.getRandomInt(0, 1), true)) {
                    this.growParticle(squareBlock)
                    squareBlock.setPermutation(squareBlock.permutation.withState("growth", growLlv + 1))
                }
            }
        }

    }

    growTree(block, container, squareBlock) {

        let treeType = "mangrove"
        if (squareBlock.typeId.includes("sapling")) {
            treeType = squareBlock.typeId.replace("minecraft:", "").replace("_sapling", "")
        }

        let price = { min: 10, max: 15 }

        const rotations = [
            "0_degrees",
            "180_degrees",
            "270_degrees",
            "90_degrees",
        ]
        const randomRotation = rotations[this.getRandomInt(0, rotations.length - 1)]

        let structLoc = { x: squareBlock.location.x - 10, y: squareBlock.location.y, z: squareBlock.location.z - 10 }

        let variant_4 = false
        if (squareBlock.typeId == "minecraft:dark_oak_sapling") {
            if (this.isPartOfHorizontalSquare(squareBlock)) {
                variant_4 = true
            } else {
                treeType = null
            }
        }
        if (squareBlock.typeId == "minecraft:pale_oak_sapling") {
            if (this.isPartOfHorizontalSquare(squareBlock)) {
                variant_4 = true
            } else {
                treeType = null
            }
        }
        if (squareBlock.typeId == "minecraft:spruce_sapling") {
            if (this.isPartOfHorizontalSquare(squareBlock)) {
                variant_4 = true
                price = { min: 25, max: 35 }
            } else {
                if (
                    squareBlock.north().typeId == "minecraft:spruce_sapling"
                    || squareBlock.south().typeId == "minecraft:spruce_sapling"
                    || squareBlock.east().typeId == "minecraft:spruce_sapling"
                    || squareBlock.west().typeId == "minecraft:spruce_sapling"
                ) {
                    treeType = null
                }
            }
        }
        if (squareBlock.typeId == "minecraft:jungle_sapling") {
            if (this.isPartOfHorizontalSquare(squareBlock)) {
                variant_4 = true
                price = { min: 25, max: 35 }
            } else {
                if (
                    squareBlock.north().typeId == "minecraft:jungle_sapling"
                    || squareBlock.south().typeId == "minecraft:jungle_sapling"
                    || squareBlock.east().typeId == "minecraft:jungle_sapling"
                    || squareBlock.west().typeId == "minecraft:jungle_sapling"
                ) {
                    treeType = null
                }
            }
        }

        if (treeType == null) return

        if (this.checkAndRemoveItems(container, "minecraft:bone_meal", this.getRandomInt(price.min, price.max), true)) {
            //  console.warn(`structure load pb_red:${variant_4 ? "4_" : ""}${treeType}_${this.getRandomInt(1, 3)} ${structLoc.x} ${structLoc.y} ${structLoc.z} ${randomRotation} none false`)
            squareBlock.dimension.runCommand(`structure load pb_red:${variant_4 ? "4_" : ""}${treeType}_${this.getRandomInt(1, 3)} ${structLoc.x} ${structLoc.y} ${structLoc.z} ${variant_4 ? rotations[0] : randomRotation} none false`)
            if (treeType == "mangrove") squareBlock.setType("minecraft:air")

            this.growParticle(squareBlock.north())
            this.growParticle(squareBlock.south())
            this.growParticle(squareBlock.east())
            this.growParticle(squareBlock.west())
        }

    }

    growGrass(block, container, squareBlock, grassType) {
        const grassTypes = [
            "minecraft:short_grass",
            "minecraft:short_grass",
            "minecraft:tall_grass",
            "minecraft:tall_grass",
            "minecraft:fern",
            "minecraft:large_fern",
            //flower
            "minecraft:poppy",
            "minecraft:dandelion",
            "minecraft:blue_orchid",
            "minecraft:allium",
            "minecraft:azure_bluet",
            "minecraft:oxeye_daisy",
            "minecraft:cornflower",
            "minecraft:lily_of_the_valley",
            "minecraft:rose_bush",
            "minecraft:pink_petals",
            "minecraft:sunflower",
            "minecraft:lilac",
            "minecraft:peony",
            "minecraft:red_tulip",
            "minecraft:orange_tulip",
            "minecraft:white_tulip",
            "minecraft:pink_tulip",
        ]
        const mossTypes = [
            "minecraft:short_grass",
            "minecraft:tall_grass",
            "minecraft:moss_carpet",
            "minecraft:moss_carpet",
            "minecraft:moss_carpet",
            "minecraft:azalea",
            "minecraft:flowering_azalea",

        ]
        const paleMossTypes = [
            "minecraft:pale_moss_carpet",
            "minecraft:pale_moss_carpet",
            "minecraft:pale_moss_carpet",
            "minecraft:short_grass",
            "minecraft:tall_grass",
            "minecraft:closed_eyeblossom",
            "minecraft:open_eyeblossom"
        ]

        if (Math.random() > 0.75) {
            if (this.checkAndRemoveItems(container, "minecraft:bone_meal", this.getRandomInt(0, 1), true)) {
                const typeList = grassType == "grass" ? grassTypes : grassType == "moss" ? mossTypes : paleMossTypes
                const randomGrass = typeList[this.getRandomInt(0, typeList.length - 1)]

                squareBlock.setType(randomGrass)
                this.growParticle(squareBlock)
            }

        }
    }

    getBlocksInSquare(center, radius, dimension) {
        const blocks = [];
        const { x, y, z } = center;

        for (let dx = -radius; dx <= radius; dx++) {
            for (let dz = -radius; dz <= radius; dz++) {
                const blockPosition = {
                    x: Math.floor(x + dx),
                    y: Math.floor(y),
                    z: Math.floor(z + dz)
                };
                const block = dimension.getBlock(blockPosition);
                if (block) {
                    blocks.push(block);
                }
            }
        }

        return blocks;
    }

    isFertilizerBlock(block) {
        return block.typeId === "pb_red:fertilizer";
    }

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

    getBlockCenter(block) {
        const blockCenter = {
            x: block.location.x + 0.5,
            y: block.location.y + 0.01,
            z: block.location.z + 0.5
        }
        return blockCenter
    }

    growParticle(block) {
        const center = this.getBlockCenter(block)
        block.dimension.spawnParticle("minecraft:crop_growth_emitter", center)
    }

    isPartOfHorizontalSquare(block) {
        if (!block) return null;

        if (
            block.south().typeId == block.typeId
            && block.east().typeId == block.typeId
            && block.south().east().typeId == block.typeId
        ) {
            return true;
        }
        return false;
    }

    checkAndRemoveItems(inventory, itemId, requiredAmount, removeItem) {
        let totalAmount = 0;
        let slotsToUpdate = [];

        // Iterate through the player's inventory to count items and track their slots
        for (let i = 0; i < inventory.size; i++) {
            const item = inventory.getItem(i);
            if (item && item.typeId === itemId) {
                totalAmount += item.amount;
                slotsToUpdate.push({
                    slot: i,
                    item,
                });
                if (totalAmount >= requiredAmount) break;
            }
        }

        // Check if the player has enough items
        if (totalAmount >= requiredAmount) {
            if (removeItem) {
                let amountToRemove = requiredAmount;

                // Remove the required amount of items from the inventory
                slotsToUpdate.forEach(({
                    slot,
                    item
                }) => {
                    if (amountToRemove > 0) {
                        if (item.amount > amountToRemove) {
                            item.amount -= amountToRemove;
                            inventory.setItem(slot, item);
                            amountToRemove = 0;
                        } else {
                            amountToRemove -= item.amount;
                            inventory.setItem(slot, null); // Clear the slot if all items are removed
                        }
                    }
                });
            }

            return true; // Successfully removed the required items
        } else {
            return false; // Not enough items
        }
    }

    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);
    }


}








function spawnAreaParticle(location, dimension, duration, areaSize) {

    const size_1 = areaSize + 0.5 + 0.01
    const size_2 = areaSize + 0.5 + 0.01

    const mvm = new MolangVariableMap();
    mvm.setFloat(`variable.duration`, duration);
    mvm.setFloat(`variable.size_1`, size_1);
    mvm.setFloat(`variable.size_2`, size_2);

    const baseX = location.x;
    const baseY = location.y;
    const baseZ = location.z;

    const faceOffsets = [
        { x: 0, y: 0, z: 0 }, // Face inférieure
        { x: 0, y: 1, z: 0 }, // Face supérieure
        { x: size_1, y: 0.5, z: 0 }, // Face devant
        { x: -size_1, y: 0.5, z: 0 }, // Face derrière
        { x: 0, y: 0.5, z: size_2 }, // Face droite
        { x: 0, y: 0.5, z: -size_2 } // Face gauche
    ];

    for (const offset of faceOffsets) {
        const faceLocation = {
            x: baseX + offset.x,
            y: baseY + offset.y,
            z: baseZ + offset.z
        };
        const index = faceOffsets.indexOf(offset)
        const id = index < 2 ? "pb_red:square_area_horizontal" : index < 4 ? "pb_red:square_area_vertical_z" : "pb_red:square_area_vertical_x"

        if (index > 1) {
            mvm.setFloat(`variable.size_1`, size_1);
            mvm.setFloat(`variable.size_2`, 0.5);
        }

        try {
            world.getDimension(dimension.id).spawnParticle(id, faceLocation, mvm);
        } catch {
            // console.error("Can't spawn Particle in unloaded Chunks");
        }
    }
}