import * as mc from "@minecraft/server"

const debug = true
const maxDistanceSpawn = 40
mc.world.beforeEvents.worldInitialize.subscribe(data => {
    data.blockComponentRegistry.registerCustomComponent("ld_eb:elemental_table", {
        onPlace: a => {
            const block = a.block
            
            block.ld_eb_id() ? null : block.ld_eb_id(randomInt(0, 9999))
            block.ld_eb_summon_entity()
        },
        onPlayerDestroy: a => {
            const block = a.block

            block.ld_eb_remove_entity()
        },
        onTick: a => {
            const block = a.block

            block.dimension.getEntities({
                families: ["ld_eb_elemental"],
                location: block.location,
                maxDistance: maxDistanceSpawn
            }).forEach(e => {
                applyExplosionImpulse(e, block.center(), 2)
            })
        }
    })
})

/**
 * Aplica um impulso de explosão afastando a entidade de um ponto central.
 * 
 * @param {Entity} entity - A entidade a ser empurrada
 * @param {Vector3} centro - O ponto central da "explosão"
 * @param {number} intensidade - A força do impulso
 * @param {boolean} ignoreY - Se verdadeiro, a explosão só afeta os eixos XZ
 */
function applyExplosionImpulse(entity, centro, intensidade = 1, ignoreY = true) {
    const origem = entity.location;

    const dx = origem.x - centro.x;
    const dy = origem.y - centro.y;
    const dz = origem.z - centro.z;

    const mag = ignoreY ? Math.hypot(dx, dz) || 0.001 : Math.sqrt(dx * dx + dy * dy + dz * dz) || 0.001;

    const nx = dx / mag;
    const ny = ignoreY ? 0 : dy / mag;
    const nz = dz / mag;

    entity.applyImpulse({
        x: nx * intensidade,
        y: ny * intensidade,
        z: nz * intensidade
    });
}

mc.Block.prototype.ld_eb_id = function (value = undefined) {
    const { x, y, z } = this.center(),
    key = `${x}, ${y}, ${z}`,
    idDynamicProperty = `ld_eb:${this.permutation.type.id}.${key}`
    if (value === undefined) {
        //!debug ? null: console1-console.warn("retornou o valor de: " + idDynamicProperty + " que é: " + mc.world.getDynamicProperty(idDynamicProperty))
        return mc.world.getDynamicProperty(idDynamicProperty)||undefined
    }
    //!debug ? null: console1-console.warn("setou " + idDynamicProperty + "de: " + mc.world.getDynamicProperty(idDynamicProperty) + " para: " + value)
    mc.world.setDynamicProperty(idDynamicProperty, value)
}
function randomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}
mc.Block.prototype.ld_eb_summon_entity = function () {
    const { x, y, z } = this.center(),
    key = `${x}, ${y}, ${z}`,
    idDynamicProperty = `ld_eb:${this.permutation.type.id}.${key}`
    const entity = this.dimension.spawnEntity("ld_eb:elemental_table", this.center())
    entity.setDynamicProperty(idDynamicProperty, this.ld_eb_id())
    //console1-console.warn("summonou " + entity.typeId + " na table: " + this.ld_eb_id())
}
mc.Block.prototype.ld_eb_remove_entity = function () {
    const { x, y, z } = this.center(),
    key = `${x}, ${y}, ${z}`,
    idDynamicProperty = `ld_eb:${this.permutation.type.id}.${key}`
    const entity = this.dimension.getEntities({
        closest: 1,
        type: "ld_eb:elemental_table",
        location: this.center()
    }).filter(e => e.getDynamicProperty(idDynamicProperty) === this.ld_eb_id())
    .forEach(e => {
        //console1-console.warn("removeu " + e.typeId + " da table: " + this.ld_eb_id())
        e.remove()
    })
}

mc.world.afterEvents.entitySpawn.subscribe(data => {
    const entitySpawned = data.entity
    try {
    const entity = entitySpawned.dimension.getEntities({
        type: entitySpawned.typeId,
        location: entitySpawned.location,
        closest: 1,
        families: ["ld_eb_elemental"]
    }).length > 0 ? entitySpawned : null
    if (entity === null) return
    entitySpawned.dimension.getEntities({
        type: "ld_eb:elemental_table",
        location: entitySpawned.location,
        maxDistance: maxDistanceSpawn
    }).length > 0 ? entitySpawned.remove() : null
    } catch (error) {
        
    }
})

mc.world.afterEvents.entityLoad.subscribe(data => {
    const entity = data.entity
    if (entity.typeId !== "ld_eb:elemental_table") return
    entity.setProperty("ld_eb:active", mc.world.getDynamicProperty("ld_eb:elemental_table_border"))
    //console1-console.warn("carregou " + entity.typeId)
})
mc.world.afterEvents.entitySpawn.subscribe(data => {
    const entity = data.entity
    if (entity.typeId !== "ld_eb:elemental_table") return
    entity.setProperty("ld_eb:active", mc.world.getDynamicProperty("ld_eb:elemental_table_border"))
    //console1-console.warn("carregou " + entity.typeId)
})