import { system, world, ItemStack, MolangVariableMap } from "@minecraft/server";
import { furnaceConfig } from "./furnaceConfig";
import * as mcUi from "@minecraft/server-ui";
import * as AxZ from "./APIs/AxZ-API";
import "./furnaceGuidebook";
import "./chestMain";
import { checkRecipe } from "./furnaceRecipes";

// Inicializar Scoreboards
world.afterEvents.worldInitialize.subscribe(xZ => {
    system.runTimeout(() => {
        if (!world.scoreboard.getObjective('vtng_fn:activeTimer')) world.scoreboard.addObjective('vtng_fn:activeTimer', 'Active Timer');
        if (!world.scoreboard.getObjective('vtng_fn:cookingTimer')) world.scoreboard.addObjective('vtng_fn:cookingTimer', 'Cooking Timer');
    }, 50);
    system.waitTicks(10).then(() => world.setDynamicProperty('vtng_fn:portal_chest', undefined));
});

// Fake Selection System
world.afterEvents.dataDrivenEntityTrigger.subscribe(({entity}) => {
    const block = entity.dimension.getBlock(entity.location); if (block.isAir) return;
    const fakeSelection = block.permutation.getState('vtng_fn:fake_selection');
    const nearestPlayer = entity.dimension.getPlayers({maxDistance: 8, location: block.center(), families: ['player'], closest: 1})[0];
    if (nearestPlayer) {
        let correctViewDirection;
        if (fakeSelection) {
            const furnaceEntity = nearestPlayer.getEntitiesFromViewDirection({maxDistance: 8, type: 'vtng_fn:furnace_inventory'})[0]?.entity;
            if (JSON.stringify(furnaceEntity?.location || {}) == JSON.stringify(entity.location)) correctViewDirection = true;
        };
        if (!fakeSelection) {
            const furnaceBlock = nearestPlayer.getBlockFromViewDirection({maxDistance: 8})?.block;
            if (JSON.stringify(furnaceBlock?.location || {}) == JSON.stringify(block.location)) correctViewDirection = true;
        };

        if (correctViewDirection) {
            if (!nearestPlayer.isSneaking && !fakeSelection) {
                entity.triggerEvent('vtng_fn:add_collision');
                block.setPermutation(block.permutation.withState('vtng_fn:fake_selection', true));
                entity.teleport(block.bottomCenter());
            };
            if (nearestPlayer.isSneaking && fakeSelection) {
                entity.triggerEvent('vtng_fn:remove_collision');
                block.setPermutation(block.permutation.withState('vtng_fn:fake_selection', false));
                entity.teleport(block.center());
            };
            if (!nearestPlayer.isSneaking) entity.dimension.spawnEntity(`vtng_fn:outline_selection`, block.center());
        };                
    } else if (!fakeSelection) {
        entity.triggerEvent('vtng_fn:add_collision');
        block.setPermutation(block.permutation.withState('vtng_fn:fake_selection', true));
        entity.teleport(block.bottomCenter());
    };

    const hasFurnaceOpen = entity.dimension.getPlayers({maxDistance: 8, location: block.center(), families: ['player'], tags: ['vtng_fn:furnace_open'], closest: 1})[0];
    if (!hasFurnaceOpen && block.permutation.getState('vtng_fn:quick_tick')) {
        block.setPermutation(block.permutation.withState('vtng_fn:quick_tick', false));
    };

    const playersUse = entity.getDynamicProperty('vtng_fn:playersUse')
    if (playersUse != undefined && playersUse != '{}' && !hasFurnaceOpen) entity.setDynamicProperty('vtng_fn:playersUse', undefined);
}, {eventTypes: ['vtng_fn:player_nearby']});

// Executa enquanto o inventario estiver aberto
world.afterEvents.dataDrivenEntityTrigger.subscribe(({entity}) => {
    // Adição de Placeholders --------
    const block = entity.dimension.getBlock(entity.location); if (block.isAir) return;
    const pocketUi = block.permutation.getState('vtng_fn:pocket_ui');
    const furnaceInfos = furnaceConfig[block.typeId][pocketUi ? 'pocketProfile' : 'classicProfile']; if (!furnaceInfos) return;
    const fuelItems = furnaceConfig[block.typeId].fuelItems;

    // Active Time
    const activeTimer = world.scoreboard.getObjective('vtng_fn:activeTimer');
    if (!activeTimer.hasParticipant(entity)) activeTimer?.addScore(entity, 0);
    const remainingFuelTime = activeTimer?.getScore(entity);

    // Cooking Time
    const cookingTimer = world.scoreboard.getObjective('vtng_fn:cookingTimer');
    if (!cookingTimer.hasParticipant(entity)) cookingTimer?.addScore(entity, 0);
    const remainingCookTime = cookingTimer?.getScore(entity);

    // XP Amount
    const xpAmount = entity.getDynamicProperty('vtng_fn:xpAmount');
    if (!xpAmount) entity.setDynamicProperty('vtng_fn:xpAmount', 0);

    // Inventory Infos
    const furnaceInv = entity?.getComponent('minecraft:inventory').container;
    const lastResult = JSON.parse(entity.getDynamicProperty('vtng_fn:last_result') || '{}');

    // Placeholder
    const slotsArray = [...furnaceInfos.inputSlots, furnaceInfos.fuelSlot, ...furnaceInfos.resultSlots, furnaceInfos.flameIconSlot, furnaceInfos.arrowIconSlot, ...furnaceInfos.uiSlots];
    for (let slot = 0; slot < furnaceInv.size; slot++) {
        if (!pocketUi) {
            if (!slotsArray.includes(slot) && (slot != 4 || furnaceInfos.displayHasName)) furnaceInv.setItem(slot, new ItemStack('vtng_fn:placeholder_invisible', 1));
            if (furnaceInfos.uiSlots.includes(slot)) furnaceInv.setItem(slot, new ItemStack(`${furnaceInfos.uiTypeId}_${slot}`, 1));
            if (slot == 4 && !furnaceInfos.displayHasName) {
                const blockName = `${block.typeId}_ui_name`; // .replace('waxed_', '').replace('exposed_', '').replace('oxidized_', '').replace('weathered_', '')
                furnaceInv.setItem(slot, new ItemStack(blockName, 1));
            };
        } else {
            if (!slotsArray.includes(slot)) furnaceInv.setItem(slot, new ItemStack(`vtng_fn:placeholder_pocket`, 1));
        };
        if (furnaceInfos.resultSlots.includes(slot) && lastResult[slot] == undefined) furnaceInv.setItem(slot, new ItemStack('vtng_fn:placeholder_invisible', 1));
        if (block.typeId.includes('log')) furnaceInv.setItem(furnaceInfos.fuelSlot, new ItemStack(`${block.typeId}_placeholder_${pocketUi ? 'pocket' : 'classic'}`, 1));
    };

    // Flame Animation
    const lastFuelId = entity.getDynamicProperty('vtng_fn:last_fuel');
    const fuelTime = block.typeId.includes('infinity') ? fuelItems[lastFuelId]?.duration * 10 : block.typeId.includes('nether') && entity.dimension.id == 'minecraft:nether' ? fuelItems[lastFuelId]?.duration * 3 : fuelItems[lastFuelId]?.duration;

    // const fuelTime = block.typeId.includes('gold') ? fuelItems[lastFuelId]?.duration / 3 
    //     : block.typeId.includes('diamond') || block.typeId.includes('emerald') ? fuelItems[lastFuelId]?.duration * 2 
    //     : block.typeId.includes('ultimate') ? fuelItems[lastFuelId]?.duration * 10 
    //     : fuelItems[lastFuelId]?.duration;

    const flameSegment = AxZ.getSegment(fuelTime, remainingFuelTime, furnaceInfos.fuelSteps+1 || 14)-1;
    const fuelIndicatorId = furnaceInfos?.fuelId || `${furnaceInfos.uiTypeId}_flame`;
    if (remainingFuelTime > 0) {
        furnaceInv.setItem(furnaceInfos.flameIconSlot, new ItemStack(`${fuelIndicatorId}_${flameSegment}`, 1));
    } else {
        furnaceInv.setItem(furnaceInfos.flameIconSlot, new ItemStack(`${fuelIndicatorId}_0`, 1));
    };


    // Arrow Animation
    const cookingTime = furnaceConfig[block.typeId].cookingSpeed;
    const arrowSegment = AxZ.getSegment(cookingTime, remainingCookTime, furnaceInfos.progressBarSteps || 22);
    const progressBarId = furnaceInfos?.progressBarId || `${furnaceInfos.uiTypeId}_arrow`;
    if (remainingCookTime > 0) furnaceInv.setItem(furnaceInfos.arrowIconSlot, new ItemStack(`${progressBarId}_${arrowSegment}`, 1));
    else furnaceInv.setItem(furnaceInfos.arrowIconSlot, new ItemStack(`${progressBarId}_0`, 1));


    // Bloqueia fornalhas para diferentes tipos de UI's
    const playersUse = JSON.parse(entity.getDynamicProperty('vtng_fn:playersUse') || '{}');
    for (let playerId of Object.keys(playersUse)) {
        const player = world.getEntity(playerId); if (!player) continue;

        // Remove os botões do inventario do jogador
        const playerInv = player.getComponent('minecraft:inventory').container;
        const playerCursor = player.getComponent('minecraft:cursor_inventory');
        const cursorItem = playerCursor.item;
        for (let slot = 0; slot < playerInv.size; slot++) {
            const item = playerInv.getItem(slot);
            if (item?.typeId.startsWith('vtng_fn:') && (item?.typeId.includes('_ui') || item?.typeId.includes('placeholder'))) {
                playerInv.setItem(slot);
            };
        };
        if (cursorItem?.typeId.startsWith('vtng_fn:') && (cursorItem?.typeId.includes('_ui') || cursorItem?.typeId.includes('placeholder'))) {
            playerCursor.clear();
        };

        if (JSON.stringify(player.getViewDirection()) != playersUse[playerId]) {
            entity.runCommandAsync('tag @a remove vtng_fn:busy_furnace');
            player.removeTag('vtng_fn:furnace_open');
            delete playersUse[playerId];
            entity.setDynamicProperty('vtng_fn:playersUse', JSON.stringify(playersUse));
            const block = entity.dimension.getBlock(entity.location); if (block.isAir) return;
        };
        if (player.hasTag('vtng_fn:configured_ui')) {
            const uiProfile = player.getDynamicProperty('vtng_fn:uiProfile');
            entity.dimension.getPlayers({maxDistance: 15, location: entity.location, families: ['player']}).forEach(nearbyPlayers => {
                if (!nearbyPlayers.hasTag('vtng_fn:busy_furnace') && nearbyPlayers.getDynamicProperty('vtng_fn:uiProfile') != uiProfile) nearbyPlayers.addTag('vtng_fn:busy_furnace');
            });
        };
    };
}, {eventTypes: ['vtng_fn:is_opened']});

// Garante q o tick pare quando a entidade for descarregada e carregada
world.afterEvents.entityLoad.subscribe(xZ => {
    if (xZ.entity.typeId != 'vtng_fn:furnace_inventory') return;
    const block = xZ.entity.dimension.getBlock(xZ.entity.location); if (block.isAir) return;
    const hasFurnaceOpen = xZ.entity.dimension.getPlayers({maxDistance: 8, location: block.center(), families: ['player'], tags: ['vtng_fn:furnace_open'], closest: 1})[0];
    if (!hasFurnaceOpen && block.permutation.getState('vtng_fn:quick_tick')) {
        block.setPermutation(block.permutation.withState('vtng_fn:quick_tick', false));
    };
});

// Remove a Tag de uso em alguns casos
world.afterEvents.playerSpawn.subscribe(xZ => {
    system.run(() => { 
        xZ.player.runCommand('tag @a remove vtng_fn:busy_furnace');
        xZ.player.removeTag('vtng_fn:furnace_open');
        xZ.player.runCommand('tag @a remove vtng_fn:busy_chest');
        xZ.player.removeTag('vtng_fn:chest_open');
    });
});
world.beforeEvents.playerLeave.subscribe(xZ => {
    if (xZ.player.hasTag('vtng_fn:furnace_open')) system.run(() => { world.getAllPlayers()[0].runCommand('tag @a remove vtng_fn:busy_furnace'); });
    if (xZ.player.hasTag('vtng_fn:chest_open')) system.run(() => { world.getAllPlayers()[0].runCommand('tag @a remove vtng_fn:busy_chest'); });
});

// Remove os itens ao morrer por /kill
world.afterEvents.entityDie.subscribe(({deadEntity, damageSource}) => {
    if (damageSource.cause != 'selfDestruct' || !deadEntity?.typeId.includes('vtng_fn') || !deadEntity?.typeId.includes('furnace')) return;
    system.run(() => {
        deadEntity.dimension.getEntities({type: 'minecraft:item', maxDistance: 2, location: deadEntity.location}).forEach(entity => {
            const item = entity.getComponent('minecraft:item').itemStack;
            if (item?.typeId.includes('_ui') || item?.typeId.includes('placeholder')) entity.remove();
        });
    });
});

// Drop ao quebrar fornalha
world.afterEvents.dataDrivenEntityTrigger.subscribe(({entity}) => {
    const furnaceId = entity.getDynamicProperty('vtng_fn:furnace_type');
    const furnaceInfos = furnaceConfig[furnaceId]; if (!furnaceInfos) return entity.remove();;
    const pocketUi = entity.getProperty('vtng_fn:pocket_ui');
    const uiProfile = furnaceInfos[pocketUi ? 'pocketProfile' : 'classicProfile'];
    const furnaceInv = entity?.getComponent('minecraft:inventory').container;

    const fuelItem = furnaceInv.getItem(uiProfile?.fuelSlot);
    if (fuelItem) entity.dimension.spawnItem(fuelItem, entity.location);
    
    uiProfile?.resultSlots.forEach(slot => {
        const resultItem = furnaceInv.getItem(slot);
        if (resultItem && !resultItem.typeId.includes('placeholder')) entity.dimension.spawnItem(resultItem, entity.location);
    });

    uiProfile?.inputSlots.forEach(slot => {
        const inputItem = furnaceInv.getItem(slot);
        if (inputItem) entity.dimension.spawnItem(inputItem, entity.location);
    });

    const xpAmount = entity.getDynamicProperty('vtng_fn:xpAmount');
    if (xpAmount >= 3) {
        for (let xp = 0; xp <= xpAmount*2; xp += 3) {
            entity.dimension.spawnEntity('minecraft:xp_orb', entity.location);
        };
    };

    if (furnaceId.includes('log_furnace')) entity.dimension.getEntities({type: 'minecraft:item', maxDistance: 2, location: entity.location}).forEach(itemEntity => {
        const item = itemEntity.getComponent('minecraft:item').itemStack;
        if (item?.typeId.includes('placeholder') || item?.typeId.includes('_ui') || (entity.hasTag('vtng_fn:burned') && item?.typeId.includes('log_furnace'))) itemEntity.remove();
    });

    entity.remove();
}, {eventTypes: ['vtng_fn:destroyed_block']});

// --------------------------------=-=-=-=-=-=-=-=-=-=-=-=-=--------------------------------

world.beforeEvents.worldInitialize.subscribe(xZ => {
    xZ.blockComponentRegistry.registerCustomComponent('vtng_fn:furnace', {
        onPlace: ({block, dimension, previousBlock}) => {
            if (!furnaceConfig[block.typeId]) return console.warn('Fornalha não configurada!'), dimension.playSound('note.bass', block.location);

            const hasChimney = furnaceConfig[block.typeId]?.chimneyCollision;
            if (hasChimney) {
                const aboveBlock = block.above();
                if (aboveBlock && aboveBlock.isAir) {
                    aboveBlock.setType('vtng_fn:chimney_collision');
                    aboveBlock.setPermutation(aboveBlock.permutation.withState('vtng_fn:furnace_type', hasChimney));
                };
            };

            if (dimension.getEntities({location: block.center(), type: `vtng_fn:furnace_inventory`, maxDistance: 0.9})[0]) return;
            const entity = dimension.spawnEntity(`vtng_fn:furnace_inventory`, block.bottomCenter()); 
            entity.setDynamicProperty('vtng_fn:furnace_type', block.typeId);
            entity.nameTag = `§r`;

            if (furnaceConfig[block.typeId]?.entityVisual) {
                block.setPermutation(block.permutation.withState('vtng_fn:placed', true));
                const blockRotation = block.permutation.getState('minecraft:cardinal_direction');
                const visualEntity = dimension.spawnEntity(`${block.typeId}_entity`, block.center());
                visualEntity.setProperty('vtng_fn:cardinal_rotation', blockRotation);
            };

            // Add Placeholder
            const furnaceInfos = furnaceConfig[block.typeId]['classicProfile']; if (!furnaceInfos) return;
            const furnaceInv = entity?.getComponent('minecraft:inventory').container;

            const slotsArray = [...furnaceInfos.inputSlots, furnaceInfos.fuelSlot, ...furnaceInfos.resultSlots, furnaceInfos.flameIconSlot, furnaceInfos.arrowIconSlot, ...furnaceInfos.uiSlots];
            for (let slot = 0; slot < furnaceInv.size; slot++) {
                if (!slotsArray.includes(slot) && (slot != 4 || furnaceInfos.displayHasName)) furnaceInv.setItem(slot, new ItemStack('vtng_fn:placeholder_invisible', 1));
                if (furnaceInfos.uiSlots.includes(slot)) furnaceInv.setItem(slot, new ItemStack(`${furnaceInfos.uiTypeId}_${slot}`, 1));
                if (slot == 4 && !furnaceInfos.displayHasName) {
                    const blockName = `${block.typeId}_ui_name`; // .replace('waxed_', '').replace('exposed_', '').replace('oxidized_', '').replace('weathered_', '')
                    furnaceInv.setItem(slot, new ItemStack(blockName, 1));
                };
                if (furnaceInfos.resultSlots.includes(slot)) furnaceInv.setItem(slot, new ItemStack('vtng_fn:placeholder_invisible', 1));
                if (block.typeId.includes('log')) furnaceInv.setItem(furnaceInfos.fuelSlot, new ItemStack(`${block.typeId}_placeholder_classic`, 1));
            };
        },
        onTick: ({block, dimension}) => {
            const entity = dimension.getEntities({location: block.center(), type: `vtng_fn:furnace_inventory`, maxDistance: 0.9})[0]; if (!entity) return;
            let visualEntity; 
            if (furnaceConfig[block.typeId].entityVisual) visualEntity = dimension.getEntities({location: block.center(), type: `${block.typeId}_entity`, maxDistance: 0.9})[0];
            const pocketUi = block.permutation.getState('vtng_fn:pocket_ui');
            const tickInterval = block.permutation.getState('vtng_fn:quick_tick') ? 1 : 5;
            const furnaceInfos = furnaceConfig[block.typeId]?.[pocketUi ? 'pocketProfile' : 'classicProfile']; if (!furnaceInfos) return;
            const furnaceRecipes = furnaceConfig[block.typeId].recipes;
            const fuelItems = furnaceConfig[block.typeId].fuelItems;
            
            // Active Time
            const activeTimer = world.scoreboard.getObjective('vtng_fn:activeTimer');
            if (!activeTimer.hasParticipant(entity)) activeTimer?.addScore(entity, 0);
            const remainingFuelTime = activeTimer?.getScore(entity);

            // Cooking Time
            const cookingTimer = world.scoreboard.getObjective('vtng_fn:cookingTimer');
            if (!cookingTimer.hasParticipant(entity)) cookingTimer?.addScore(entity, 0);
            const remainingCookTime = cookingTimer?.getScore(entity);

            // XP Amount
            let xpAmount = entity.getDynamicProperty('vtng_fn:xpAmount');
            if (!xpAmount) entity.setDynamicProperty('vtng_fn:xpAmount', 0);

            // Inventory Infos
            const furnaceInv = entity?.getComponent('minecraft:inventory').container;
            const inputItems = furnaceInfos.inputSlots.map(slot => furnaceInv.getItem(slot));
            const resultItems = furnaceInfos.resultSlots.map(slot => furnaceInv.getItem(slot));
            const fuelItem = (() => { const item = furnaceInv.getItem(furnaceInfos.fuelSlot); return item && fuelItems[item.typeId] ? item : undefined; })();
            const lastResult = JSON.parse(entity.getDynamicProperty('vtng_fn:last_result') || '{}');
            
            const hasValidPair = furnaceInfos.inputSlots.some((inputSlot, index) => {
                const inputItem = inputItems[index];
                const resultItem = resultItems[index];
                const recipe = furnaceRecipes[inputItem?.typeId];

                if (!inputItem) return false;
                if (inputItem && !recipe) {
                    checkRecipe(inputItem?.typeId, block.location, dimension);
                    return false;
                };
            
                const expectedResult = recipe.output;
                const resultIsPlaceholder = !resultItem || resultItem.typeId.includes('placeholder');
                const resultIsSame = resultItem?.typeId === expectedResult && resultItem?.amount < 64;
            
                return resultIsPlaceholder || resultIsSame;
            });

            // Xp Drop
            const playersUse = JSON.parse(entity.getDynamicProperty('vtng_fn:playersUse') || '{}');
            let player; if (Object.keys(playersUse).length) player = world.getEntity(Object.keys(playersUse)[0]);
            if (player) {
                let shouldDropXp = false;
                for (let i = 0; i < furnaceInfos.resultSlots.length; i++) {
                    const slot = furnaceInfos.resultSlots[i];
                    const resultItem = resultItems[i];
            
                    if (!resultItem && lastResult[slot] !== undefined) {
                        lastResult[slot] = undefined;
                        shouldDropXp = true;
                        break;
                    };
                };
            
                if (shouldDropXp) {
                    entity.setDynamicProperty('vtng_fn:last_result', JSON.stringify(lastResult));
                    if (xpAmount >= 3) {
                        entity.dimension.spawnEntity('minecraft:xp_orb', player.location);
                        player.addExperience(xpAmount - 3);
                        entity.setDynamicProperty('vtng_fn:xpAmount', 0);
                    };
                };
            };

            // Fuel System
            const isRedstoneFurnace = block.typeId.includes('redstone');
            const fuelDuration = fuelItems[fuelItem?.typeId]?.duration;
            if (remainingFuelTime <= 0) {
                block.setPermutation(block.permutation.withState('vtng_fn:furnace_on', false));
                visualEntity?.setProperty('vtng_fn:furnace_on', false);
                activeTimer?.addScore(entity, 0);
            };

            const blockPowered = AxZ.getRedstonePower(block) > 0;
            if (isRedstoneFurnace && (fuelItem || blockPowered) && remainingFuelTime + (fuelDuration || 0) < 300 + (fuelDuration || 0)) {
                if (fuelItem && !blockPowered) furnaceInv.setItem(furnaceInfos.fuelSlot, fuelItem?.amount > 1 ? new ItemStack(fuelItem?.typeId, fuelItem?.amount - 1) : undefined);
                entity.setDynamicProperty('vtng_fn:last_fuel', 'vtng_fn:redstone_energy');
                activeTimer.addScore(entity, blockPowered ? 1 : fuelDuration);
                block.setPermutation(block.permutation.withState('vtng_fn:furnace_on', true));
            } else if (fuelItem && hasValidPair && remainingFuelTime <= tickInterval) {
                if (!block.typeId.includes('log') && !fuelItem.typeId.includes('bucket')) {
                    furnaceInv.setItem(furnaceInfos.fuelSlot, fuelItem?.amount > 1 ? new ItemStack(fuelItem?.typeId, fuelItem?.amount - 1) : undefined);
                } else if (fuelItem.typeId.includes('bucket')) {
                    furnaceInv.setItem(furnaceInfos.fuelSlot, new ItemStack('minecraft:bucket', 1));
                };
                entity.setDynamicProperty('vtng_fn:last_fuel', fuelItem?.typeId);

                // Tempo de queima do combustível
                const fuelTime = block.typeId.includes('infinity') ? fuelDuration * 10 : block.typeId.includes('nether') && dimension.id == 'minecraft:nether' ? fuelDuration * 3 : fuelDuration;

                activeTimer.addScore(entity, fuelTime);
                block.setPermutation(block.permutation.withState('vtng_fn:furnace_on', true));
                visualEntity?.setProperty('vtng_fn:furnace_on', true);
                if (block.typeId.includes('infinity')) block.dimension.playSound('block.end_portal.spawn', block.center(), { pitch: 1.25 });
            };
            if (remainingFuelTime > 0 && !(isRedstoneFurnace && blockPowered)) activeTimer?.addScore(entity, -tickInterval);


            // Arrow Control
            if (hasValidPair && remainingFuelTime > 0) cookingTimer?.addScore(entity, tickInterval);
            if (remainingCookTime > 0 && remainingFuelTime <= 0) cookingTimer?.addScore(entity, -tickInterval);
            if (!hasValidPair) cookingTimer?.setScore(entity, 0);
            
            const lastFuelId = entity.getDynamicProperty('vtng_fn:last_fuel');
            
            // Cooking System
            const cookingTime = furnaceConfig[block.typeId].cookingSpeed;
            if (hasValidPair && remainingCookTime >= cookingTime) {
                cookingTimer?.setScore(entity, 0);
            
                furnaceInfos.inputSlots.forEach((inputSlot, index) => {
                    const resultSlot = furnaceInfos.resultSlots[index];
                    const inputItem = inputItems[index];
                    const resultItem = resultItems[index];
                    const recipe = furnaceRecipes[inputItem?.typeId];
            
                    if (!inputItem || !recipe) return;
            
                    const expectedResult = recipe.output;
                    const canPlaceResult = !resultItem || resultItem.typeId.includes('placeholder') || (resultItem.typeId === expectedResult && resultItem.amount < 64);
            
                    if (!canPlaceResult) return;
            
                    // COZINHAR TUDO DE UMA VEZ
                    if (block.typeId.includes('infinity')) {
                        const availableSpace = 64 - (resultItem?.typeId.includes('placeholder') ? 0 : resultItem?.amount ?? 0);
                        const cookingAmount = Math.min(availableSpace, inputItem.amount);
                        if (cookingAmount <= 0) return;

                        furnaceInv.setItem(inputSlot, inputItem.amount > cookingAmount ? new ItemStack(inputItem.typeId, inputItem.amount - cookingAmount) : undefined);
                        furnaceInv.setItem( resultSlot,
                            (resultItem?.typeId.includes('placeholder') ? 0 : resultItem?.amount ?? 0) === 0 || resultItem.typeId.includes('placeholder')
                                ? new ItemStack(expectedResult, cookingAmount)
                                : new ItemStack(expectedResult, (resultItem?.amount ?? 0) + cookingAmount)
                        );
                    } else {
                        furnaceInv.setItem(inputSlot, inputItem.amount > 1 ? new ItemStack(inputItem.typeId, inputItem.amount - 1) : undefined);
                        
                        if (!resultItem || resultItem.typeId.includes('placeholder')) furnaceInv.setItem(resultSlot, new ItemStack(expectedResult, 1));
                        else furnaceInv.setItem(resultSlot, new ItemStack(expectedResult, resultItem.amount + 1));
                    };
            
                    lastResult[resultSlot] = expectedResult;
                    xpAmount += block.typeId.includes('crystal') ? recipe.xp * 5 : block.typeId.includes('infinity') ? recipe.xp * inputItem.amount : recipe.xp;
                });
                entity.setDynamicProperty('vtng_fn:last_result', JSON.stringify(lastResult));
                entity.setDynamicProperty('vtng_fn:xpAmount', xpAmount);
            };

            // Wood Furnaces Ability
            if (block.typeId.includes('log')) {
                if (remainingFuelTime > 0 && remainingFuelTime <= tickInterval) entity.runCommand('setblock ~~~ air destroy');
                const burningStage = 4 - AxZ.getSegment(fuelItems[lastFuelId]?.duration, remainingFuelTime, 4);
                if (!Number.isNaN(burningStage) && !block.isAir) block.setPermutation(block.permutation.withState('vtng_fn:burning_stage', burningStage == 4 ? 0 : burningStage));
                
                if (remainingFuelTime > 0) entity.addTag('vtng_fn:burned');
            };

            // Copper Furnace Oxidize
            //if (block.typeId.includes('copper') && !block.typeId.includes('waxed') && !block.typeId.includes('oxidized')) {
            //    if (Math.random() < 0.00005 * tickInterval) {
            //        const states = block.permutation.getAllStates();
            //        if (block.typeId.includes('exposed')) block.setType(block.typeId.replace('exposed_copper', 'weathered_copper'));
            //        else if (block.typeId.includes('weathered')) block.setType(block.typeId.replace('weathered_copper', 'oxidized_copper'));
            //        else block.setType(block.typeId.replace('copper', 'exposed_copper'));
            //        for (let state in states) {
            //            block.setPermutation(block.permutation.withState(state, states[state]));
            //        };
            //    };
            //};

            // Furnace Sounds
            if (remainingFuelTime > 0 && remainingFuelTime % 5 == 0) {
                if (!block.typeId.includes('ice') && Math.random() < 0.3 * tickInterval) {
                    block.dimension.playSound('block.furnace.lit', block.center());
                };
            };
            if (block.typeId.includes('infinity') && Math.random() < 0.1 * tickInterval) block.dimension.playSound('portal.portal', block.center(), { pitch: 0.65, volume: 0.1 });


            // Furnace Particles
            if (remainingFuelTime > 0 && Math.random() < 0.025 * tickInterval) {
                const randomPoint = { y: Math.random() * (0.4 - 0) + 0, xz: Math.random() * (0.4 - -0.4) + -0.4 };
                const particlePoint = {
                    'north': { x: randomPoint.xz, y: randomPoint.y, z: -0.51 }, 'south': { x: randomPoint.xz, y: randomPoint.y, z: 0.51 },
                    'east': { x: 0.51, y: randomPoint.y, z: randomPoint.xz }, 'west': { x: -0.51, y: randomPoint.y, z: randomPoint.xz }
                };
                const particlePos = new AxZ.somarVetores(block.bottomCenter(), particlePoint[block.permutation.getState('minecraft:cardinal_direction')]);
                if (block.typeId.includes('redstone')) block.dimension.spawnParticle('minecraft:redstone_wire_dust_particle', particlePos);
                else if (block.typeId.includes('copper')) block.dimension.spawnParticle('vtng_fn:basic_copper_flame', particlePos);
                else if (block.typeId.includes('ice')) {
                    block.dimension.spawnParticle('minecraft:falling_dust_top_snow_particle', particlePos);
                    block.dimension.playSound('hit.powder_snow', block.center());
                } else if (block.typeId.includes('crystal')) {
                    block.dimension.spawnParticle('minecraft:blue_flame_particle', particlePos);
                } else {
                    block.dimension.spawnParticle('minecraft:basic_flame_particle', particlePos);
                };
                if (!block.typeId.includes('ice') && !block.typeId.includes('redstone')) block.dimension.spawnParticle('minecraft:basic_smoke_particle', particlePos);
            };
            return;
        }
    });
    xZ.blockComponentRegistry.registerCustomComponent('vtng_fn:furnace_placeholder', {
        onPlace: xZ => { xZ.block.setType('minecraft:air'); }
    });
    xZ.blockComponentRegistry.registerCustomComponent('vtng_fn:chimney', {
        onPlayerDestroy: xZ => {
            const { block, dimension } = xZ;
            const furnaceBlock = block.below();
            if (furnaceConfig[furnaceBlock.typeId]?.chimneyCollision) {
                dimension.runCommand(`setblock ${furnaceBlock.x} ${furnaceBlock.y} ${furnaceBlock.z} air destroy`);
            };
        }
    });
});

// Faz a compatibilidade com o hopper a cada 0.4s
world.afterEvents.dataDrivenEntityTrigger.subscribe(({entity}) => {
    const block = entity.dimension.getBlock(entity?.location); if (block?.isAir || !block) return;
    const pocketUi = block.permutation.getState('vtng_fn:pocket_ui');
    const furnaceInfos = furnaceConfig[block.typeId][pocketUi ? 'pocketProfile' : 'classicProfile']; if (!furnaceInfos) return;
    const fuelItems = furnaceConfig[block.typeId].fuelItems;

    // Inventory Infos
    const furnaceInv = entity?.getComponent('minecraft:inventory').container;
    const resultItems = furnaceInfos.resultSlots.map(slot => furnaceInv.getItem(slot));
    const fuelItem = (() => { const item = furnaceInv.getItem(furnaceInfos.fuelSlot); return item && fuelItems[item.typeId] ? item : undefined; })();

    hopperCompatibility(block, furnaceInv, furnaceInfos, fuelItem, fuelItems, resultItems);
}, {eventTypes: ['vtng_fn:hopper_compatibility']});


// Interação com a entidade, configuração inicial e tag de funcionamento
world.afterEvents.playerInteractWithEntity.subscribe(xZ => {
    const { player, target: entity, itemStack } = xZ;
    if (!entity?.typeId.includes('vtng_fn') || !entity?.typeId.includes('furnace')) return;

    if (!player.hasTag('vtng_fn:configured_ui')) configUiProfile(player);
    if (player.hasTag('vtng_fn:configured_ui') && player.hasTag('vtng_fn:busy_furnace')) {
        return player.sendMessage({translate: 'text.vtng_fn.busy_furnace' }), player.playSound('note.bell', {location: player.location});
    };

    if (player.hasTag('vtng_fn:configured_ui') && !player.hasTag('vtng_fn:busy_furnace')) {
        player.addTag('vtng_fn:furnace_open');
        const uiProfile = player.getDynamicProperty('vtng_fn:uiProfile');
        const block = entity.dimension.getBlock(entity.location); if (block.isAir) return;
        block.setPermutation(block.permutation.withState('vtng_fn:quick_tick', true));

        const pocketUi = block.permutation.getState('vtng_fn:pocket_ui');
        if (uiProfile == 'vtng_fn:uiClassic' && pocketUi) {
            block.setPermutation(block.permutation.withState('vtng_fn:pocket_ui', false));
            entity.setProperty('vtng_fn:pocket_ui', false);

            // Muda a posição dos itens de pocket para classic
            const furnaceInfos = furnaceConfig[block.typeId]; if (!furnaceInfos) return;
            const furnaceInv = entity?.getComponent('minecraft:inventory').container;
            transferProfileItems(furnaceInfos.pocketProfile, furnaceInfos.classicProfile, furnaceInv);
        };
        if (uiProfile == 'vtng_fn:uiPocket' && !pocketUi) {
            block.setPermutation(block.permutation.withState('vtng_fn:pocket_ui', true));
            entity.setProperty('vtng_fn:pocket_ui', true);

            // Muda a posição dos itens de pocket para classic
            const furnaceInfos = furnaceConfig[block.typeId]; if (!furnaceInfos) return;
            const furnaceInv = entity?.getComponent('minecraft:inventory').container;
            transferProfileItems(furnaceInfos.classicProfile, furnaceInfos.pocketProfile, furnaceInv);
        };

        system.runTimeout(() => {
            const playersUse = JSON.parse(entity.getDynamicProperty('vtng_fn:playersUse') || '{}');
            playersUse[player.id] = JSON.stringify(player.getViewDirection())
            entity.setDynamicProperty('vtng_fn:playersUse', JSON.stringify(playersUse));
        }, 5);
    };
});

world.beforeEvents.playerInteractWithBlock.subscribe(xZ => {
    if (!xZ.block.typeId.includes('copper') || !xZ.block.typeId.startsWith('vtng_fn:') || !xZ.isFirstEvent) return;
    
    if (xZ.itemStack.hasTag("minecraft:is_axe")) {
        system.run(() => {
            // Copper Furnace Deoxidation
            if (!xZ.block.typeId.includes('waxed') && !xZ.block.typeId.startsWith('vtng_fn:copper')) {
                const states = xZ.block.permutation.getAllStates();
                if (xZ.block.typeId.includes('exposed')) xZ.block.setType(xZ.block.typeId.replace('exposed_copper', 'copper'));
                else if (xZ.block.typeId.includes('weathered')) xZ.block.setType(xZ.block.typeId.replace('weathered_copper', 'exposed_copper'));
                else xZ.block.setType(xZ.block.typeId.replace('oxidized_copper', 'weathered_copper'));
                for (let state in states) {
                    xZ.block.setPermutation(xZ.block.permutation.withState(state, states[state]));
                };

                const particleColor = new MolangVariableMap();
                particleColor.setColorRGB('color', { red: 0.36, green: 0.72, blue: 0.62 });
                xZ.block.dimension.spawnParticle('vtng_fn:copper_wax', xZ.block.center(), particleColor);
            };

            // Copper Furnace De-Wax
            if (xZ.block.typeId.includes('waxed')) {
                const states = xZ.block.permutation.getAllStates();
                xZ.block.setType(xZ.block.typeId.replace('vtng_fn:waxed_', 'vtng_fn:'));
                for (let state in states) {
                    xZ.block.setPermutation(xZ.block.permutation.withState(state, states[state]));
                };

                const particleColor = new MolangVariableMap();
                particleColor.setColorRGB('color', { red: 1, green: 1, blue: 1 });
                xZ.block.dimension.spawnParticle('vtng_fn:copper_wax', xZ.block.center(), particleColor);
            };
        });
    };

    if (xZ.itemStack.typeId == 'minecraft:honeycomb') {
        // Copper Furnace Wax
        system.run(() => {
            if (!xZ.block.typeId.includes('waxed')) {
                const states = xZ.block.permutation.getAllStates();
                xZ.block.setType(xZ.block.typeId.replace('vtng_fn:', 'vtng_fn:waxed_'));
                for (let state in states) {
                    xZ.block.setPermutation(xZ.block.permutation.withState(state, states[state]));
                };

                const particleColor = new MolangVariableMap();
                particleColor.setColorRGB('color', { red: 1, green: 0.5, blue: 0 });
                xZ.block.dimension.spawnParticle('vtng_fn:copper_wax', xZ.block.center(), particleColor);
            };
        });
    };
});

// --------- ÁREA DE FUNÇÕES -------

export function configUiProfile(player) {
    const configForm = new mcUi.ActionFormData();
    configForm.title('vtng_fn.configUi.tittle');
    configForm.body('vtng_fn.configUi.body');
    configForm.button('vtng_fn.configUi.classic', 'textures/vtng/fn/ui/classic_button');
    configForm.button('vtng_fn.configUi.pocket', 'textures/vtng/fn/ui/pocket_button');
    configForm.show(player).then(r => {
        if (r.canceled) return;
        if (r.selection == 0) uiProfileConfirmationForm(player, 'vtng_fn:uiClassic');
        if (r.selection == 1) uiProfileConfirmationForm(player, 'vtng_fn:uiPocket');
    });
};

export function uiProfileConfirmationForm(player, uiProfile) {
    const confirmationForm = new mcUi.ActionFormData();
    confirmationForm.title('vtng_fn.confirmationUi.tittle');
    confirmationForm.body('vtng_fn.confirmationUi.body');
    confirmationForm.button('gui.yes', 'textures/ui/realms_green_check');
    confirmationForm.button('gui.no', 'textures/ui/realms_red_x');
    confirmationForm.show(player).then(r => {
        if (r.canceled || r.selection == 1) return;
        else {
            player.addTag('vtng_fn:configured_ui');
            player.removeTag('vtng_fn:busy_chest')
            player.setDynamicProperty('vtng_fn:uiProfile', uiProfile);
        };
    });
};

function transferProfileItems(sourceProfile, targetProfile, furnaceInv) {
    // Copia os itens dos slots de origem
    const fuelItem = furnaceInv.getItem(sourceProfile.fuelSlot);
    const inputItems = sourceProfile.inputSlots.map(slot => furnaceInv.getItem(slot));
    const resultItems = sourceProfile.resultSlots.map(slot => furnaceInv.getItem(slot));

    // Limpa os slots de origem para evitar sobrescrita
    furnaceInv.setItem(sourceProfile.fuelSlot, undefined);
    sourceProfile.inputSlots.forEach(slot => furnaceInv.setItem(slot, undefined));
    sourceProfile.resultSlots.forEach(slot => furnaceInv.setItem(slot, undefined));

    // Inserir os itens nos slots de destino
    furnaceInv.setItem(targetProfile.fuelSlot, fuelItem);
    targetProfile.inputSlots.forEach((slot, index) => {
        if (slot !== undefined) furnaceInv.setItem(slot, inputItems[index]);
    });
    targetProfile.resultSlots.forEach((slot, index) => {
        if (slot !== undefined) furnaceInv.setItem(slot, resultItems[index]);
    });
};

function hopperCompatibility(block, furnaceInv, config, fuelItem, fuelItems, resultItems) {
    const allFaces = ['north', 'south', 'east', 'west', 'above', 'below']; 
    const hopperRot = { 'north': 3, 'south': 2, 'east': 4, 'west': 5, 'above': 0 };
    for (let face of allFaces) {
        const hopperBlock = block[face](furnaceConfig[block.typeId]?.chimneyCollision && face == 'above' ? 2 : 1);
        if (hopperBlock?.typeId != 'minecraft:hopper') continue;        
        if (hopperBlock.permutation.getState('facing_direction') == hopperRot[face] || face == 'below') {
            const hopperInv = hopperBlock.getComponent('minecraft:inventory')?.container; if (!hopperInv) continue;
            if (['north', 'south', 'east', 'west'].includes(face) && (!fuelItem || fuelItem?.amount < 64)) {
                for (let slot = 0; slot < hopperInv.size; slot++) {
                    const item = hopperInv.getItem(slot); if (!item || !fuelItems[item?.typeId]) continue;
                    if (fuelItems[item?.typeId] && (!fuelItem || fuelItem?.typeId == item?.typeId)) {
                        hopperInv.setItem(slot, item?.amount > 1 ? new ItemStack(item?.typeId, item?.amount - 1) : undefined);
                        furnaceInv.setItem(config.fuelSlot, new ItemStack(item?.typeId, (fuelItem ? fuelItem?.amount : 0) + 1));
                        break;
                    };
                };
            };
            if (face === 'above') {
                hopperCheck: for (let hopperSlot = 0; hopperSlot < hopperInv.size; hopperSlot++) {
                    const item = hopperInv.getItem(hopperSlot); if (!item) continue;
                    for (let slot of config.inputSlots) {
                        let slotItem = furnaceInv.getItem(slot);
                        if (!slotItem) {
                            hopperInv.setItem(hopperSlot, item.amount > 1 ? new ItemStack(item.typeId, item.amount - 1) : undefined);
                            furnaceInv.setItem(slot, new ItemStack(item.typeId, 1));
                            break hopperCheck;
                        } else if (slotItem?.typeId === item.typeId && slotItem?.amount < 64) {
                            hopperInv.setItem(hopperSlot, item.amount > 1 ? new ItemStack(item.typeId, item.amount - 1) : undefined);
                            furnaceInv.setItem(slot, new ItemStack(slotItem.typeId, (slotItem ? slotItem.amount : 0) + 1));
                            break hopperCheck;
                        };
                    };
                };
            };
            if (face === 'below') {
                furnaceCheck: for (let i = 0; i < config.resultSlots.length; i++) {
                    const resultSlot = config.resultSlots[i];
                    const resultItem = resultItems[i];
                    if (!resultItem || resultItem.typeId.includes('placeholder')) continue;
            
                    for (let slot = 0; slot < hopperInv.size; slot++) {
                        const hopperItem = hopperInv.getItem(slot);
                        if (!hopperItem) {
                            furnaceInv.setItem(resultSlot, resultItem.amount > 1 ? new ItemStack(resultItem.typeId, resultItem.amount - 1) : undefined);
                            hopperInv.addItem(new ItemStack(resultItem.typeId, 1));
                            break furnaceCheck;
                        } else if (hopperItem.typeId === resultItem.typeId && hopperItem.amount < 64) {
                            furnaceInv.setItem(resultSlot, resultItem.amount > 1 ? new ItemStack(resultItem.typeId, resultItem.amount - 1) : undefined);
                            hopperInv.setItem(slot, new ItemStack(hopperItem.typeId, hopperItem.amount + 1));
                            break furnaceCheck;
                        };
                    };
                };
            };
        };
    };
};
