import * as mc from "@minecraft/server"
import * as lib from "../lib"
import { difficultyDamageController } from './index'

let damageMultiplier = 7
const delayVelocityMultiplier = 0.5

const entityType = {
    typeId: "ld_eb:spirit_elemental",
    skills: [
        { delay: delayVelocityMultiplier * 2, damage: damageMultiplier * 1, id: 0, chance: 3, anim: "attack" },
        { delay: delayVelocityMultiplier * 2, damagePS: damageMultiplier, id: 1, chance: 3, anim: "soul_drain" },
        { delay: delayVelocityMultiplier * 2, damagePS: damageMultiplier, id: 2, chance: 3, anim: "phantom_assault" },
        { delay: delayVelocityMultiplier * 3, damagePS: damageMultiplier, id: 3, chance: 3, anim: "haunting_wail" }
    ]
}

mc.Entity.prototype.ld_eb_inAttack = false

mc.system.afterEvents.scriptEventReceive.subscribe(async ({ sourceEntity: entity, id }) => {
    if (entity.typeId !== entityType.typeId || entity.ld_eb_inAttack) return
    entity.triggerEvent("ld_eb:cancel_rotation")

    const skillIndex = parseInt(id.split("_").pop())
    if (!isNaN(skillIndex) && skills[skillIndex]) skills[skillIndex].start(entity)

    const next = lib.randomWithChances(entityType.skills)
    entity.setProperty("ld_eb:proximo_ataque", next)
    entity.triggerEvent("ld_eb:skill_" + next + "_intention")
})

const skills = entityType.skills.map((skill, i) => ({
    index: i,
    start: async function (entity) {
        if (ifDead(entity)) return

        entity.ld_eb_inAttack = true
        entity.addEffect("slowness", 9999999, { showParticles: false, amplifier: 255 })
        entity.playAnimation(skill.anim)

        const locator = lib.locator(entity, { z: 2 })
        await mc.system.waitTicks(4)
        if (ifDead(entity)) return

        if (skill.id === 0) {
            mc.world.playSound("ld_eb.spirit_elemental.attack", locator.location, { pitch: 1, volume: 20 })
            await mc.system.waitTicks(2)
            if (ifDead(entity)) return
            lib.getEntities(locator, 10).filter(e => e !== entity).forEach(e => {
                e.applyDamage(skill.damage)
                try { e.applyKnockback(entity.getViewDirection().x, entity.getViewDirection().z, 2, 0.2) } catch {}
            })

        } else {
            const spell = lib.locator(locator)
            await mc.system.waitTicks(2)
            if (ifDead(entity)) return

            mc.world.playSound(`ld_eb.spirit_elemental.${skill.id}`, locator.location, { pitch: 1, volume: 20 })

            const targets = lib.getEntities(locator, skill.id === 3 ? 5 : 10).filter(e => e !== entity)
            targets.forEach(e => {
                if (skill.damagePS) e.applyDamage(skill.damagePS)
                if (skill.id === 1) lib.middleImpulse(e, entity, 1, 0.1)
                else try { e.applyKnockback(entity.getViewDirection().x, entity.getViewDirection().z, skill.id === 2 ? 1.5 : 3, skill.id === 2 ? 0.5 : 0.8) } catch {}

                const tick = mc.system.runInterval(() => {
                    if (!spell.isValid() || ifDead(entity)) return mc.system.clearRun(tick)
                    if (skill.damagePS) e.applyDamage(skill.damagePS)
                    if (skill.id === 1) lib.middleImpulse(e, entity, 1, 0.1)
                    else try { e.applyKnockback(entity.getViewDirection().x, entity.getViewDirection().z, skill.id === 2 ? 1.5 : 3, skill.id === 2 ? 0.5 : 0.8) } catch {}
                }, 10)
            })

            await mc.system.waitTicks(skill.id === 2 ? 30 : 20)
            if (spell.isValid()) spell.remove()
        }

        await mc.system.waitTicks(Math.max(2, skill.delay * 20))
        if (ifDead(entity)) return
        entity.removeEffect("slowness")
        entity.ld_eb_inAttack = false
        entity.triggerEvent("ld_eb:remove_cancel_rotation")
    }
}))

mc.world.afterEvents.entityLoad.subscribe(({ entity }) => {
    if (entity.typeId !== entityType.typeId) return
    entity.removeEffect("slowness")
    entity.triggerEvent("ld_eb:remove_cancel_rotation")
})

function ifDead(entity) {
    const health = entity.getComponent(mc.EntityHealthComponent.componentId)
    return !health || health.currentValue <= 1
}
