
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:air_elemental",
    skills: [
        { delay: delayVelocityMultiplier * 2, damage: damageMultiplier  * (mc.world.getDifficulty()=='Easy'?0.8:mc.world.getDifficulty()=='Normal'?1:mc.world.getDifficulty()=='Hard'?1.6:1), id: 0, chance: 3, anim: "attack" },
        { delay: delayVelocityMultiplier * 2, damagePS: damageMultiplier * 1, id: 1, chance: 3, anim: "cyclone_swipe" },
        { delay: delayVelocityMultiplier * delayVelocityMultiplier * 0.1, damagePS: damageMultiplier * 1, id: 2, chance: 3, anim: "air_blade" },
        { delay: delayVelocityMultiplier * 3, damagePS: damageMultiplier * 1, id: 3, chance: 3, anim: "gale_force_push" }
    ]
};

mc.Entity.prototype.ld_eb_inAttack = false;

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

    const index = parseInt(id.split("_").pop());
    if (skills[index]) skills[index].start(entity);

    entity.setProperty("ld_eb:proximo_ataque", lib.randomWithChances(entityType.skills));
    entity.triggerEvent("ld_eb:skill_" + entity.getProperty("ld_eb:proximo_ataque") + "_intention");
});

const skills = [
    {
        index: 0,
        async start(entity) {
            entity.ld_eb_inAttack = true;
            entity.addEffect("slowness", 9999999, { showParticles: false, amplifier: 255 });
            entity.playAnimation(entityType.skills[this.index].anim);
            const locator = lib.locator(entity, { z: 2 });

            await mc.system.waitTicks(0.4 * 20);
            if (ifDead(entity)) return;

            if (mc.world.getDynamicProperty("ld_eb:efeitos_sonoros"))
                mc.world.playSound("ld_eb.air_elemental.attack", locator.location, { pitch: 1, volume: 20 });

            await mc.system.waitTicks(0.1 * 20);
            if (ifDead(entity)) return;

            lib.getEntities(locator, 10).filter(e => e !== entity).forEach(e => {
                e.applyDamage(entityType.skills[this.index].damage*difficultyDamageController);
                try { e.applyKnockback(entity.getViewDirection().x, entity.getViewDirection().z, 2, 0.2); } catch {}
            });

            await mc.system.waitTicks(Math.max(0.1, entityType.skills[this.index].delay) * 20);
            if (ifDead(entity)) return;

            entity.removeEffect("slowness");
            entity.ld_eb_inAttack = false;
            entity.triggerEvent("ld_eb:remove_cancel_rotation");
        }
    },
    {
        index: 1,
        async start(entity) {
            entity.ld_eb_inAttack = true;
            entity.addEffect("slowness", 9999999, { showParticles: false, amplifier: 255 });
            entity.playAnimation(entityType.skills[this.index].anim);
            const locator = lib.locator(entity, { z: 2 });

            await mc.system.waitTicks(0.1 * 20);
            if (ifDead(entity)) return;

            if (mc.world.getDynamicProperty("ld_eb:efeitos_sonoros"))
                mc.world.playSound("ld_eb.air_elemental.1", locator.location, { pitch: 1, volume: 20 });

            const spell = lib.locator(locator);

            await mc.system.waitTicks(0.1 * 20);
            if (ifDead(entity)) return;

            lib.getEntities(locator, 10).filter(e => e !== entity).forEach(e => {
                e.applyDamage(entityType.skills[this.index].damagePS*difficultyDamageController);
                const tick = mc.system.runInterval(() => {
                    if (!spell.isValid()) return mc.system.clearRun(tick);
                    e.applyDamage(entityType.skills[this.index].damagePS*difficultyDamageController);
                    try { e.applyKnockback(entity.getViewDirection().x, entity.getViewDirection().z, 0, 0.3); } catch {}
                }, 10);
                e.addEffect("levitation", 20, { showParticles: false, amplifier: 5 });
            });

            await mc.system.waitTicks(1.5 * 20);
            if (ifDead(entity)) return;
            spell.remove();

            await mc.system.waitTicks(Math.max(0.1, entityType.skills[this.index].delay) * 20);
            if (ifDead(entity)) return;

            entity.removeEffect("slowness");
            entity.ld_eb_inAttack = false;
            entity.triggerEvent("ld_eb:remove_cancel_rotation");
        }
    },
    {
        index: 2,
        async start(entity) {
            entity.ld_eb_inAttack = true;
            entity.addEffect("slowness", 9999999, { showParticles: false, amplifier: 255 });
            entity.playAnimation(entityType.skills[this.index].anim);
            const locator = lib.locator(entity, { z: 1, y: 2 });

            await mc.system.waitTicks(0.1 * 20);
            if (ifDead(entity)) return;

            const spell = lib.spell(
                "ld_eb:ld_eb_air_cut",
                entity,
                { z: 1, y: 2 },
                { y: entity.getRotation().y + 180, z: lib.random(-20, 20) }
            );

            lib.ProjectileShoot(spell, { x: 2, y: 0.5, z: 2 });

            const tick = mc.system.runInterval(() => {
                if (!spell.isValid()) return mc.system.clearRun(tick);

                if (mc.world.getDynamicProperty("ld_eb:efeitos_sonoros"))
                    mc.world.playSound("ld_eb.air_elemental.2", locator.location, { pitch: 1, volume: 20 });

                lib.getEntities(spell, 4).filter(e => e !== entity).forEach(e => {
                    e.applyDamage(entityType.skills[this.index].damagePS*difficultyDamageController);
                    try { e.applyKnockback(entity.getViewDirection().x, entity.getViewDirection().z, 3, 0.1); } catch {}
                });
            }, 1);

            await mc.system.waitTicks(2 * 20);
            if (ifDead(entity)) return;
            spell.remove();

            await mc.system.waitTicks(Math.max(0.1, entityType.skills[this.index].delay) * 20);
            if (ifDead(entity)) return;

            entity.removeEffect("slowness");
            entity.ld_eb_inAttack = false;
            entity.triggerEvent("ld_eb:remove_cancel_rotation");
        }
    },
    {
        index: 3,
        async start(entity) {
            entity.ld_eb_inAttack = true;
            entity.addEffect("slowness", 9999999, { showParticles: false, amplifier: 255 });
            entity.playAnimation(entityType.skills[this.index].anim);
            const locator = lib.locator(entity, { z: 2 });

            await mc.system.waitTicks(0.1 * 20);
            const spell = lib.locator(locator);
            await mc.system.waitTicks(0.2 * 20);
            if (ifDead(entity)) return;

            if (mc.world.getDynamicProperty("ld_eb:efeitos_sonoros"))
                mc.world.playSound("ld_eb.air_elemental.3", locator.location, { pitch: 1, volume: 20 });

            await mc.system.waitTicks(0.4 * 20);
            if (ifDead(entity)) return;

            const dim = spell.dimension;
            for (let i = 1; i <= 7; i++) {
                dim.spawnParticle(`ld_eb:air_mob_gale_force_push_${i}`, spell.location);
            }

            lib.getEntities(locator, 16).filter(e => e !== entity).forEach(e => {
                e.applyDamage(entityType.skills[this.index].damagePS*difficultyDamageController);
                const tick = mc.system.runInterval(() => {
                    if (!spell.isValid()) return mc.system.clearRun(tick);
                    e.applyDamage(entityType.skills[this.index].damagePS*difficultyDamageController);
                    lib.middleImpulse(e, entity, 1, 1);
                }, 10);
                e.addEffect("levitation", 2 * 20, { showParticles: false, amplifier: 5 });
            });

            await mc.system.waitTicks(1.5 * 20);
            if (ifDead(entity)) return;
            spell.remove();

            await mc.system.waitTicks(Math.max(0.1, entityType.skills[this.index].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(data => {
    const entity = data.entity;
    if (entity.typeId !== entityType.typeId) return;
    entity.removeEffect("slowness");
    entity.triggerEvent("ld_eb:remove_cancel_rotation");
});

/** @param { mc.Entity } entity */
function ifDead(entity) {
    const health = entity.getComponent(mc.EntityHealthComponent.componentId);
    return !health || health.currentValue <= 1;
}
