import { Block, Dimension, Entity, ItemStack } from "@minecraft/server";
import { blockNeighbors } from "../../../library/blockManager";


const chestTypes = [
    "minecraft:chest",
    "minecraft:trapped_chest",
    "minecraft:barrel",
]

/**
 * Evento onTick del componente itemTransferNodeComponent
 * Addon: Electrical Creativity BP
 * @param {{entity: Entity, block: Block, dimension: Dimension}} event
 */
export const itemTransferNodeOnTickEvent = ({entity, block, dimension}) => {
    try {
        const power = block.permutation.getState("nps_ec:power");
        const active = block.permutation.getState("nps_ec:active");
        if (!power || !active) return;
        
        const direction = block.permutation.getState("minecraft:cardinal_direction");

        const checkBlocks = itemTransferNodeCheckBlocks(dimension, block, direction);
        const chest = chestInBack(block, direction);

        if (!chest) return;
        if (!checkBlocks.result) return;
        
        if (chestTypes.includes(checkBlocks.blockNeighbor.typeId) || checkBlocks.blockNeighbor.typeId.includes("_shulker_box")) {
            const chestFind = checkBlocks.blockNeighbor;
            const chestBackInventory = chest.getComponent("inventory").container;
            const chestFrontInventory = chestFind.getComponent("inventory").container;

            for (let i = 0; i < chestBackInventory.size; i++) {
                const item = chestBackInventory.getItem(i);
                if (item) {
                    let complete = false;
                    const itemCount = item.amount;
                    const itemType = item.typeId;

                    // Verificar si el cofre de atrás tiene espacio
                    for (let j = 0; j < chestFrontInventory.size; j++) {
                        const itemFront = chestFrontInventory.getItem(j);
                        if (itemFront) {
                            if (itemFront.typeId === itemType && itemFront.amount < itemFront.maxAmount) {
                                const transferAmount = Math.min(itemCount, itemFront.maxAmount - itemFront.amount);
                                chestBackInventory.setItem(i, (itemCount - transferAmount <= 0 ? null : new ItemStack(itemType, itemCount - transferAmount)));
                                chestFrontInventory.setItem(j, new ItemStack(itemType, itemFront.amount + transferAmount));
                                dimension.runCommand(`playsound random.pop @a ${block.location.x} ${block.location.y} ${block.location.z}`);
                                complete = true;
                                break;
                            }
                        } else {
                            // Si el slot está vacío, transferir el ítem
                            const itemClone = chestBackInventory.getItem(i).clone();

                            chestBackInventory.setItem(i, null);
                            chestFrontInventory.setItem(j, itemClone);
                            dimension.runCommand(`playsound random.pop @a ${block.location.x} ${block.location.y} ${block.location.z}`);
                            complete = true;
                            break;
                        }
                    }
                    if(complete) break;
                }
            }
        }
    } catch { }
}


const chestInBack = (block, direction) => {
    const { blockNeighborEast,
        blockNeighborNorth,
        blockNeighborWest,
        blockNeighborSouth } = blockNeighbors(block);

    switch (direction) {
        case 'north':
            if (chestTypes.includes(blockNeighborNorth.typeId) || blockNeighborNorth.typeId.includes("_shulker_box")) {
                return blockNeighborNorth;
            }
            break;
        case 'south':
            if (chestTypes.includes(blockNeighborSouth.typeId) || blockNeighborSouth.typeId.includes("_shulker_box")) {
                return blockNeighborSouth;
            }
            break;
        case 'west':
            if (chestTypes.includes(blockNeighborWest.typeId) || blockNeighborWest.typeId.includes("_shulker_box")) {
                return blockNeighborWest;
            }
            break;
        case 'east':
            if (chestTypes.includes(blockNeighborEast.typeId) || blockNeighborEast.typeId.includes("_shulker_box")) {
                return blockNeighborEast;
            }
            break;
        default:
            return undefined;
    }
}


/**
 * Escanea los bloques en un rango de 8 bloques para encontrar un cofre.
 * @param {Dimension} dimension 
 * @param {Block} block 
 * @param {string} direction 
 * @returns {{result: boolean, blockNeighbor: Block}}
 */
const itemTransferNodeCheckBlocks = (dimension, block, direction) => {
    const whiteList = ["minecraft:air"];
    for (let i = 1; i <= 10; i++) {
        let blockNeighbor;

        // Determinar la posición del bloque vecino según la dirección
        switch (direction) {
            case "north":
                blockNeighbor = dimension.getBlock({ x: block.location.x, y: block.location.y, z: block.location.z + i });
                break;
            case "south":
                blockNeighbor = dimension.getBlock({ x: block.location.x, y: block.location.y, z: block.location.z - i });
                break;
            case "west":
                blockNeighbor = dimension.getBlock({ x: block.location.x + i, y: block.location.y, z: block.location.z });
                break;
            case "east":
                blockNeighbor = dimension.getBlock({ x: block.location.x - i, y: block.location.y, z: block.location.z });
                break;
            default:
                return { result: false, blockNeighbor: null };
        }

        // Si el bloque es aire, continuar buscando
        if (whiteList.includes(blockNeighbor.typeId)) {
            continue;
        }

        // Si se encuentra un cofre, devolver el resultado
        if (chestTypes.includes(blockNeighbor.typeId) || blockNeighbor.typeId.includes("_shulker_box")) {
            return { result: true, blockNeighbor };
        }

        // Si no es un cofre ni aire, detener la búsqueda
        return { result: false, blockNeighbor };
    }

    // Si no se encuentra un cofre en el rango, devolver falso
    return { result: false, blockNeighbor: null };
};