import { system, world, MolangVariableMap } from "@minecraft/server"
import { startBlockLocationProperty } from "./blocks"
import { distance, sendDebugMessage } from "./JM_Utils"

const heartFillOrder = ["lb_as:armor_leather", "lb_as:armor_gold", "lb_as:armor_iron", "lb_as:armor_diamond"]

world.afterEvents.entityDie.subscribe(deathEvent => {
    try {
        const deadEntity = deathEvent.deadEntity
        const type = deadEntity.typeId
        try {
            var dimension = deadEntity.dimension
        } catch (error) {
            return
        }
        // skip if entity doesn't have block location stored (this can happen if the spawn was not instigated as intended, i.e., player manipulation)
        if (!deadEntity.getDynamicPropertyIds().includes(startBlockLocationProperty)) return
        const center = deadEntity.getDynamicProperty(startBlockLocationProperty)
        const variables = new MolangVariableMap()
        const dist = distance(center, deadEntity.location)
        const time = dist/4
        variables.setFloat("dx", center.x - deadEntity.location.x)
        variables.setFloat("dy", center.y - deadEntity.location.y)
        variables.setFloat("dz", center.z - deadEntity.location.z)
        variables.setFloat("dist", dist)
        variables.setFloat("time", time)
        dimension.spawnParticle("lb_as:heart_trail", deadEntity.location, variables)
        system.runTimeout(() => {
            const block = dimension.getBlock(center)
            // if the block is unavailable or gone, do nothing
            if (!block || block.typeId !== "lb_as:heart_block") return
            const state = block.permutation.getState("lb_as:heart_filled")
            const thisEntityBitPosition = heartFillOrder.indexOf(type)
            block.setPermutation(block.permutation.withState("lb_as:heart_filled", state | (1 << thisEntityBitPosition)))
            block.dimension.playSound("heart_fill", block.center())
        }, Math.floor(time * 20))
    } catch (error) {
        sendDebugMessage(error)
    }
})

world.afterEvents.entityDie.subscribe(deathEvent => {
    //boss and miniboss spawn entities
    const spawns = ['lb_as:armor_commander', 'lb_as:armor_captain', 'lb_as:armor_general']
    if (spawns.includes(deathEvent.deadEntity.typeId)) {
        deathEvent.deadEntity.dimension.getEntities({type:'lb_as:boss_3'}).forEach(boss => {
            boss.triggerEvent('decrement_shield')
        })
        deathEvent.deadEntity.dimension.getEntities({type:'lb_as:armor_iron'}).forEach(miniBoss => {
            miniBoss.triggerEvent('decrement_shield')
        })
    }
})

world.afterEvents.entityHealthChanged.subscribe(changeEvent => {
    if (changeEvent.entity.typeId === 'lb_as:boss_3') {
        if (changeEvent.oldValue >= 50 && changeEvent.newValue < 50) {
            changeEvent.entity.triggerEvent('decrement_shield')
        }
    } else if (changeEvent.entity.typeId === 'lb_as:armor_iron') {
        if (changeEvent.oldValue >= 15 && changeEvent.newValue < 15) {
            changeEvent.entity.triggerEvent('decrement_shield')
        }
    }
})