import * as mc from "@minecraft/server"
import * as ui from "@minecraft/server-ui"


mc.system.afterEvents.scriptEventReceive.subscribe(data => {
    const id = data.id,
    source = data.sourceEntity
    if (id !== "ld_eb:book_interact") return
    if (buttons.some(b => b.type !== source.typeId)) return;

    const mainEntity = findMainEntity(source);
    buttons.forEach(({ id, action }) => {
        if (id === source.getDynamicProperty("cb_sr:buttonId")) {
            action(mainEntity, source, source.getDynamicProperty("cb_sr:id"), source.getDynamicProperty("cb_sr:buttonId"));
        }
    });
})

mc.world.beforeEvents.worldInitialize.subscribe(data => {
    data.itemComponentRegistry.registerCustomComponent("ld_eb:guide_book", {
        onUseOn: (a) => {
            const player = a.source
            /** @type { mc.EntityEquippableComponent } */
            const equippable = player.getComponent(mc.EntityEquippableComponent.componentId)
            equippable.setEquipment(mc.EquipmentSlot.Mainhand)
            startInterface(player)
        }
    })
})

// 📌 Configuração da interface e botões
const main = {
    type: "ld_eb:guide_book",
    onStart: /** @param {mc.Entity} entity @param {mc.Player} player */ async (entity, player) => {
        // Ajustando a posição e rotação para sempre estar corretamente na frente do jogador
        entity.setRotation({ x: 0, y: player.getRotation().y + 180 });
        entity.ld_eb_book_interactible = false
        mc.system.runTimeout(() => entity.ld_eb_book_interactible = true, 1 * 20)
    }
};
mc.Entity.prototype.ld_eb_is_removed = false
mc.Entity.prototype.ld_eb_book_interactible = true
let delayButton = 0.6
const buttons = [
    {
        type: "ld_eb:guide_book.page", id: 1, offset: { x: -0.75, y: 0, z: 0.4 }, rotation: { x: 0, y: -10 }, action: (main, button, interfaceId, buttonId) => {
            if (main.getProperty("ld_eb:page") <= 1) return
            if (!main.ld_eb_book_interactible) return
            if (main.ld_eb_is_removed) return;
            main.ld_eb_book_interactible = false
            mc.system.runTimeout(() => main.ld_eb_book_interactible = true, delayButton * 20)
            main.setProperty("ld_eb:page",  main.getProperty("ld_eb:page") - 1)
            main.playAnimation("animation.ld_eb_book.page_down")
            mc.world.playSound("item.book.page_turn", main.location)
        }
    },
    {
        type: "ld_eb:guide_book.page", id: 2, offset: { x: 0.75, y: 0, z: 0.4 }, rotation: { x: 0, y: 10 }, action: (main, button, interfaceId, buttonId) => {
            if (main.getProperty("ld_eb:page") >= 11) return
            if (!main.ld_eb_book_interactible) return
            if (main.ld_eb_is_removed) return;
            main.ld_eb_book_interactible = false
            mc.system.runTimeout(() => main.ld_eb_book_interactible = true, delayButton * 20)
            main.setProperty("ld_eb:page",  main.getProperty("ld_eb:page") + 1)
            main.playAnimation("animation.ld_eb_book.page_up")
            mc.world.playSound("item.book.page_turn", main.location)
        }
    },
];

// 📌 Detectar clique nos botões
mc.world.afterEvents.entityHitEntity.subscribe(async ({ hitEntity, damagingEntity }) => {
    if (buttons.some(b => b.type !== hitEntity.typeId)) return;
    /** @type { mc.Entity } */
    const mainEntity = findMainEntity(hitEntity);
    if (mainEntity.ld_eb_is_removed) return;
    mainEntity.ld_eb_is_removed = true
    mainEntity.playAnimation("animation.ld_eb_book.close", {
        controller: "none",
        blendOutTime: 0,
        nextState: "none"
    })
    await mc.system.waitTicks(1.3 * 20)
    mainEntity.dimension.spawnItem(new mc.ItemStack("ld_eb:guide_book_item"), mainEntity.location)
    removeInterface(damagingEntity, hitEntity)
});

/**
 * Inicializa a interface de escolha de habilidade.
 * @param {mc.Player} player - O jogador que vai usar a interface.
 */
async function startInterface(player) {
    const idInterface = getRandomInteger(0, 9999)
    const interfacePos = anchor(player.getViewDirection(), player.location, { x: 0, y: 0, z: 2 });
    
    const entity = player.dimension.spawnEntity(main.type, interfacePos);
    entity.setDynamicProperty("cb_sr:id", idInterface);

    mc.system.run(() => {
        main.onStart(entity, player)
        buttons.forEach(({ id, offset, type, rotation }) => {
            const buttonPos = anchor(player.getViewDirection(), interfacePos, offset);
            const button = entity.dimension.spawnEntity(type, buttonPos);
            button.setRotation({ x: rotation.x, y: player.getRotation().y + 180 + rotation.y });
            button.setDynamicProperty("cb_sr:buttonId", id);
            button.setDynamicProperty("cb_sr:id", idInterface);
        });
    });

}

/**
 * Remove Interface.
 * @param {mc.Player} player - O jogador que vai usar a interface.
 * @param {mc.Block} block - O bloco do altar de magia.
 * @param {mc.Number} idInterface - O ID da interface.
 */
async function removeInterface(player, entity = undefined, location = undefined) {
    if (entity === undefined) {
        entity = player.dimension.getEntities({
            type: main.type,
            closest: 1,
            location: location
        })[0]
    }
    player.inputPermissions.movementEnabled = true;

    const mainEntity = findMainEntity(entity);
    await mc.system.waitTicks(0.1 * 20);
    mainEntity.remove();
}

// 📌 Encontrar entidade principal da interface
function findMainEntity(entity) {
    return entity.dimension.getEntities({ type: main.type })
        .find(e => e.getDynamicProperty("cb_sr:id") === entity.getDynamicProperty("cb_sr:id"));
}

// 📌 Posicionamento correto dos botões com rotação ajustada
function anchor(dir, pos, offset) {
    const yawRad = Math.atan2(dir.z, dir.x); // Obtém o ângulo de rotação do jogador

    // Converte o offset para coordenadas baseadas na rotação do jogador
    const xOffset = Math.cos(yawRad) * offset.z - Math.sin(yawRad) * offset.x;
    const zOffset = Math.sin(yawRad) * offset.z + Math.cos(yawRad) * offset.x;

    return {
        x: pos.x + xOffset,
        y: pos.y + offset.y,
        z: pos.z + zOffset,
    };
}

// 📌 Funções auxiliares
const getRandomInteger = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;

mc.world.beforeEvents.entityRemove.subscribe(data => {
    const entity = data.removedEntity
    if (entity.typeId !== main.type) return

    const location = entity.location,
        dimension = entity.dimension,
        id = entity.getDynamicProperty("cb_sr:id")

    mc.system.run(() => {
        dimension.getEntities({ types: [...buttons.map(b => b.type)] })
            .filter(e => e.getDynamicProperty("cb_sr:id") === id)
            .forEach(e => e.remove());
    })
})