import { world, system, BlockPermutation, ItemStack } from "@minecraft/server";
import { Vector } from './vector.js';


export class SuperSmelterComponent {
    constructor() {
        this.onStepOn = this.onStepOn.bind(this);
        this.onPlayerInteract = this.onPlayerInteract.bind(this);

        this.FURNACE_RECIPES = [

            // ores
            { product: "minecraft:coal", ingredient: "minecraft:coal_ore" },
            { product: "minecraft:coal", ingredient: "minecraft:deepslate_coal_ore" },
            { product: "minecraft:iron_ingot", ingredient: "minecraft:iron_ore" },
            { product: "minecraft:iron_ingot", ingredient: "minecraft:deepslate_iron_ore" },
            { product: "minecraft:gold_ingot", ingredient: "minecraft:gold_ore" },
            { product: "minecraft:gold_ingot", ingredient: "minecraft:deepslate_gold_ore" },
            { product: "minecraft:copper_ingot", ingredient: "minecraft:copper_ore" },
            { product: "minecraft:copper_ingot", ingredient: "minecraft:deepslate_copper_ore" },
            { product: "minecraft:emerald", ingredient: "minecraft:emerald_ore" },
            { product: "minecraft:emerald", ingredient: "minecraft:deepslate_emerald_ore" },
            { product: "minecraft:diamond", ingredient: "minecraft:diamond_ore" },
            { product: "minecraft:diamond", ingredient: "minecraft:deepslate_diamond_ore" },
            { product: "minecraft:lapis_lazuli", ingredient: "minecraft:lapis_ore" },
            { product: "minecraft:lapis_lazuli", ingredient: "minecraft:deepslate_lapis_ore" },
            { product: "minecraft:redstone", ingredient: "minecraft:redstone_ore" },
            { product: "minecraft:redstone", ingredient: "minecraft:deepslate_redstone_ore" },
            { product: "minecraft:quartz", ingredient: "minecraft:quartz_ore" },
            { product: "minecraft:gold_ingot", ingredient: "minecraft:nether_gold_ore" },

            { product: "minecraft:gold_ingot", ingredient: "minecraft:raw_gold" },
            { product: "minecraft:copper_ingot", ingredient: "minecraft:raw_copper" },
            { product: "minecraft:iron_ingot", ingredient: "minecraft:raw_iron" },
            { product: "minecraft:netherite_scrap", ingredient: "minecraft:ancient_debris" },

            // blocks
            { product: "minecraft:stone", ingredient: "minecraft:cobblestone" },
            { product: "minecraft:cracked_stone_bricks", ingredient: "minecraft:stone_bricks" },

            { product: "minecraft:smooth_basalt", ingredient: "minecraft:basalt" },
            { product: "minecraft:smooth_stone", ingredient: "minecraft:stone" },
            { product: "minecraft:smooth_quartz", ingredient: "minecraft:quartz_block" },
            { product: "minecraft:cracked_polished_blackstone_bricks", ingredient: "minecraft:polished_blackstone_bricks" },
            { product: "minecraft:netherbrick", ingredient: "minecraft:netherrack" },
            { product: "minecraft:cracked_nether_bricks", ingredient: "minecraft:nether_brick" },

            { product: "minecraft:cracked_deepslate_bricks", ingredient: "minecraft:deepslate_bricks" },
            { product: "minecraft:cracked_deepslate_tiles", ingredient: "minecraft:deepslate_tiles" },
            { product: "minecraft:deepslate", ingredient: "minecraft:cobbled_deepslate" },

            { product: "minecraft:glass", ingredient: "minecraft:sand" },
            { product: "minecraft:glass", ingredient: "minecraft:red_sand" },
            { product: "minecraft:smooth_red_sandstone", ingredient: "minecraft:red_sandstone" },
            { product: "minecraft:smooth_sandstone", ingredient: "minecraft:sandstone" },

            { product: "minecraft:brick", ingredient: "minecraft:clay_ball" },
            { product: "minecraft:hardened_clay", ingredient: "minecraft:clay" },

            // food
            { product: "minecraft:cooked_porkchop", ingredient: "minecraft:porkchop" },
            { product: "minecraft:cooked_beef", ingredient: "minecraft:beef" },
            { product: "minecraft:cooked_chicken", ingredient: "minecraft:chicken" },
            { product: "minecraft:cooked_mutton", ingredient: "minecraft:mutton" },
            { product: "minecraft:cooked_rabbit", ingredient: "minecraft:rabbit" },
            { product: "minecraft:baked_potato", ingredient: "minecraft:potato" },
            { product: "minecraft:cooked_cod", ingredient: "minecraft:cod" },
            { product: "minecraft:cooked_salmon", ingredient: "minecraft:salmon" },

            // other
            { product: "minecraft:dried_kelp", ingredient: "minecraft:kelp" },
            { product: "minecraft:sponge", ingredient: "minecraft:wet_sponge" },
            { product: "minecraft:green_dye", ingredient: "minecraft:cactus" },
            { product: "minecraft:lime_dye", ingredient: "minecraft:sea_pickle" },
            { product: "minecraft:popped_chorus_fruit", ingredient: "minecraft:chorus_fruit" },

        ];

        this.goldItems = [
            "minecraft:golden_helmet",
            "minecraft:golden_chestplate",
            "minecraft:golden_leggings",
            "minecraft:golden_boots",
            "minecraft:golden_sword",
            "minecraft:golden_shovel",
            "minecraft:golden_pickaxe",
            "minecraft:golden_axe",
            "minecraft:golden_hoe",
            "minecraft:golden_horse_armor"
        ];

        this.ironItems = [
            "minecraft:iron_helmet",
            "minecraft:iron_chestplate",
            "minecraft:iron_leggings",
            "minecraft:iron_boots",
            "minecraft:iron_sword",
            "minecraft:iron_shovel",
            "minecraft:iron_pickaxe",
            "minecraft:iron_axe",
            "minecraft:iron_hoe",
            "minecraft:iron_horse_armor",
            "minecraft:chainmail_helmet",
            "minecraft:chainmail_chestplate",
            "minecraft:chainmail_leggings",
            "minecraft:chainmail_boots"
        ];


    }

    onPlayerInteract(e) {
        const block = e.block;
        const direction = this.getDirection(block)

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

        if (handItem) {
            if (handItem.typeId == "pb_red:redstone_wrench") {
                // switch conveyor direction
                block.dimension.runCommand(`playsound vr.stutterturn @a ${block.location.x} ${block.location.y} ${block.location.z}`)
                block.setPermutation(block.permutation.withState("minecraft:cardinal_direction", this.getOppositeDirection(direction)))
                return;
            }
        }
    }

    getDirection(block) {
        return block.permutation.getState("minecraft:cardinal_direction")
    }

    getOppositeDirection(direction) {
        switch (direction) {
            case 'north':
                return 'south';
            case 'south':
                return 'north';
            case 'east':
                return 'west';
            case 'west':
                return 'east';
            case 'up':
                return 'down';
            case 'down':
                return 'up';
            default:
                return null;  // If the direction is invalid
        }
    }

    getFrontandBack(direction, block) {
        let frontOffset, leftOffset;
        switch (direction) {
            case 'north':
                frontOffset = { x: 0, y: 0, z: -1 }
                leftOffset = { x: -1, y: 0, z: 0 }
                break;
            case 'south':
                frontOffset = { x: 0, y: 0, z: 1 }
                leftOffset = { x: 1, y: 0, z: 0 }
                break;
            case 'east':
                frontOffset = { x: 1, y: 0, z: 0 }
                leftOffset = { x: 0, y: 0, z: -1 }
                break;
            case 'west':
                frontOffset = { x: -1, y: 0, z: 0 }
                leftOffset = { x: 0, y: 0, z: 1 }
                break;
        }
        return { frontOffset, leftOffset }
    }

    onStepOn(e) {
        const block = e.block;
        let direction = block.permutation.getState('minecraft:cardinal_direction');
        let { frontOffset, leftOffset } = this.getFrontandBack(direction, block);

        if (!frontOffset) return

        for (const aboveEntity of block.dimension.getEntitiesAtBlockLocation(block.location)) {
            if (aboveEntity.typeId === 'minecraft:player') {
                return;
            }

            let entityLoc = aboveEntity.location;

            const blockCenterX = block.location.x + 0.5;
            const blockCenterZ = block.location.z + 0.5;

            // Align entity along the x or z axis based on direction
            if (Math.abs(frontOffset.x) > Math.abs(frontOffset.z)) {
                if (entityLoc.z > blockCenterZ + 0.1) {
                    aboveEntity.teleport({ x: entityLoc.x, y: entityLoc.y + 0.05, z: blockCenterZ });
                } else if (entityLoc.z < blockCenterZ - 0.1) {
                    aboveEntity.teleport({ x: entityLoc.x, y: entityLoc.y + 0.05, z: blockCenterZ });
                }
            } else {
                if (entityLoc.x > blockCenterX + 0.1) {
                    aboveEntity.teleport({ x: blockCenterX, y: entityLoc.y + 0.05, z: entityLoc.z });
                } else if (entityLoc.x < blockCenterX - 0.1) {
                    aboveEntity.teleport({ x: blockCenterX, y: entityLoc.y + 0.05, z: entityLoc.z });
                }
            }

            aboveEntity.clearVelocity();

            let impulseVector = { x: frontOffset.x / 3, y: frontOffset.y + 0.05, z: frontOffset.z / 3 };

            const container = block.above();

            if (aboveEntity.typeId === "minecraft:item" && this.isValidContainer(container)) {
                let inventory = container?.getComponent("minecraft:inventory")?.container;
                let item = aboveEntity.getComponent('minecraft:item').itemStack;

                const findRecipeByIngredient = (ingredient) => {
                    return (
                        this.FURNACE_RECIPES.find(recipe => recipe.ingredient === ingredient)
                        || this.ironItems.includes(item.typeId)
                        || this.goldItems.includes(item.typeId)
                        || item.typeId.includes("wood")
                        || item.typeId.includes("log")
                        || item.typeId.includes("stripped_log")
                        || item.typeId.includes("stripped_wood")
                        || item.typeId.includes("terracotta")
                    );
                };

                if (findRecipeByIngredient(item.typeId) !== undefined) {

                    const coalCost = 1;
                    let availableCoal = this.checkAndRemoveItems(inventory, "minecraft:coal", 0, false);
                    let availableCharcoal = this.checkAndRemoveItems(inventory, "minecraft:charcoal", 0, false);

                    const totalFuelAvailable = availableCoal + availableCharcoal;

                    if (totalFuelAvailable > 0) {
                        // Calculer le nombre d'items qui peuvent être smeltés
                        const itemsToSmelt = Math.min(item.amount, totalFuelAvailable * coalCost);
                        const itemsLeftover = item.amount - itemsToSmelt;

                        // Retirer le carburant nécessaire
                        if (availableCoal > 0) {
                            this.checkAndRemoveItems(inventory, "minecraft:coal", Math.ceil(itemsToSmelt / coalCost), true);
                        } else {
                            this.checkAndRemoveItems(inventory, "minecraft:charcoal", Math.ceil(itemsToSmelt / coalCost), true);
                        }

                        const loc = aboveEntity.location
                        // Smelt les items disponibles
                        this.smeltItem(aboveEntity, item, itemsToSmelt, impulseVector);

                        // Drop le surplus d'ingrédients non utilisés
                        if (itemsLeftover > 0) {
                            const newItemEntity = block.dimension.spawnItem(new ItemStack(item.typeId, itemsLeftover), { x: loc.x, y: loc.y + 0.05, z: loc.z });
                            newItemEntity.applyImpulse(impulseVector);

                        }
                    }
                }

            }

            try {

                aboveEntity.applyImpulse(impulseVector);
            } catch { }


        }
    }


    smeltItem(aboveEntity, item, amountToSmelt, impulseVector) {
        const loc = aboveEntity.location;
        const dimension = aboveEntity.dimension;

        let recipe = this.FURNACE_RECIPES.find(r => r.ingredient === item.typeId);
        let newId = null;

        if (!recipe) {
            if (item.typeId.includes("terracotta") && !item.typeId.includes("glazed")) {
                const parts = item.typeId.replace("minecraft:", "").replace("terracotta", "")
                newId = `minecraft:${parts}glazed_terracotta`
                if (item.typeId == "minecraft:light_gray_terracotta") newId = "minecraft:silver_glazed_terracotta"
            } else if (this.ironItems.includes(item.typeId)) {
                newId = "minecraft:iron_nugget"
            } else if (this.goldItems.includes(item.typeId)) {
                newId = "minecraft:gold_nugget"
            } else if (
                item.typeId.includes("wood")
                || item.typeId.includes("log")
                || item.typeId.includes("stripped_log")
                || item.typeId.includes("stripped_wood")
            ) {
                newId = "minecraft:charcoal"
            }
        } else {
            newId = recipe.product;
        }
        if (newId == null) return

        aboveEntity.remove();

        dimension.spawnParticle("minecraft:basic_flame_particle", { x: loc.x + 0.2, y: loc.y + 0.15, z: loc.z })
        dimension.spawnParticle("minecraft:basic_flame_particle", { x: loc.x - 0.2, y: loc.y + 0.15, z: loc.z })
        dimension.spawnParticle("minecraft:basic_flame_particle", { x: loc.x, y: loc.y + 0.15, z: loc.z + 0.2 })
        dimension.spawnParticle("minecraft:basic_flame_particle", { x: loc.x, y: loc.y + 0.15, z: loc.z - 0.2 })

        dimension.spawnParticle("minecraft:basic_smoke_particle", Vector.add(loc, Vector.multiply(impulseVector, 2.5)))
        dimension.runCommand(`playsound block.blastfurnace.fire_crackle @a ${loc.x} ${loc.y + 0.3} ${loc.z}`)

        let spawnLoc = { x: loc.x, y: loc.y + 0.03, z: loc.z }
        const newItemEntity = dimension.spawnItem(new ItemStack(newId, amountToSmelt), spawnLoc);
        newItemEntity.teleport(spawnLoc)

        newItemEntity.applyImpulse(impulseVector);


    }

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

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

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

        if (!removeItem) return totalAmount

        // 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
        }
    }


}