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:fire_elemental",
    skills: [
        { delay: delayVelocityMultiplier * 2,damage: damageMultiplier * 1, id: 0, chance: 3, anim: "attack" },
        { delay: delayVelocityMultiplier * 2, damagePS: damageMultiplier * 1, id: 1, chance: 3, anim: "inferno_chain" },
        { delay: delayVelocityMultiplier * 5,damage: damageMultiplier * 1, id: 2, chance: 3, anim: "flame_tornado" },
        { delay: delayVelocityMultiplier * 3, damagePS: damageMultiplier * 1, id: 3, chance: 3, anim: "lava_burst" }
    ]
};

mc.Entity.prototype.ld_eb_inAttack = false;
mc.Entity.prototype.owner = null;

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

    entity.triggerEvent("ld_eb:cancel_rotation");

    const index = parseInt(data.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 = [
    {
        start: async function (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(10);
            if (ifDead(entity)) return;

            if (mc.world.getDynamicProperty("ld_eb:efeitos_sonoros"))
                mc.world.playSound("ld_eb.fire_elemental.attack", locator.location, { pitch: 1, volume: 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(4, 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: 0
    },
    {
        start: async function (entity) {
            if (ifDead(entity)) return;
            entity.ld_eb_inAttack = true;
            entity.addEffect("slowness", 9999999, { showParticles: false, amplifier: 255 });
            entity.playAnimation(entityType.skills[this.index].anim);

            const locator = lib.spell("ld_eb:ld_eb_fire_chain", entity, { z: 0, y: 2 }, {
                y: entity.getRotation().y + 180,
                z: lib.random(-20, 20)
            });
            if (ifDead(entity)) return;

            const saveEntity = lib.getEntities(locator, 20).filter(e => e !== entity)[0];
            lib.ProjectileShoot(locator, { x: 1, y: 1, z: 1 });
            locator.owner = entity;

            entity.teleport(entity.location, { facingLocation: saveEntity.location });

            await mc.system.waitTicks(Math.max(4, 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
    },
    {
        start: async function (entity) {
            if (ifDead(entity)) return;
            entity.ld_eb_inAttack = true;
            entity.addEffect("slowness", 9999999, { showParticles: false, amplifier: 255 });
            entity.playAnimation(entityType.skills[this.index].anim);

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

            const spell = lib.spell("ld_eb:ld_eb_fire_tornado", entity, { z: 3 });
            if (ifDead(entity)) return;

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

            let tick = mc.system.runInterval(() => {
                if (!spell.isValid() || ifDead(entity)) {
                    try {
                    spell.remove();
                    } catch (error) {
                    }
                    return mc.system.clearRun(tick);
                }
                lib.getEntities(spell, 4).filter(e => e !== entity).forEach(e => {
                    e.applyDamage(entityType.skills[this.index].damage*difficultyDamageController * 0.01);
                    try { e.applyKnockback(entity.getViewDirection().x, entity.getViewDirection().z, 0.05, 0.005); } catch {}
                });
            });

            await mc.system.waitTicks(48);
            if (ifDead(entity)) return;

            const locator = lib.locator(spell);
            locator.setRotation(entity.getRotation());
            lib.ProjectileShoot(locator, { x: 2, y: 1, z: 2 });

            tick = mc.system.runInterval(() => {
                if (!locator.isValid() || ifDead(entity)) {
                    locator.remove();
                    return mc.system.clearRun(tick);
                }
                lib.getEntities(locator, 4).filter(e => e !== entity).forEach(async e => {
                    e.runCommand("fill ~~~ ~~~ fire replace air");
                    await mc.system.waitTicks(1);
                    e.runCommand("fill ~2~2~2 ~-2~-2~-2 air replace fire");
                    await mc.system.waitTicks(4);
                    if (mc.world.getDynamicProperty("ld_eb:efeitos_sonoros"))
                        mc.world.playSound("ld_eb.rockpunch", locator.location, {
                            pitch: lib.random(1, 1.7)
                        });
                    e.applyDamage(entityType.skills[this.index].damage*difficultyDamageController);
                    try { e.applyKnockback(entity.getViewDirection().x, entity.getViewDirection().z, 2, 0.3); } catch {}
                });
            });

            await mc.system.waitTicks(20);
            spell.remove();

            await mc.system.waitTicks(Math.max(4, 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
    },
    {
        start: async function (entity) {
            if (ifDead(entity)) return;
            entity.ld_eb_inAttack = true;
            entity.addEffect("slowness", 9999999, { showParticles: false, amplifier: 255 });
            entity.playAnimation(entityType.skills[this.index].anim);

            await mc.system.waitTicks(10);
            if (ifDead(entity)) return;

            const spell = lib.locatorEntity(entity, { y: 0 });
            if (mc.world.getDynamicProperty("ld_eb:efeitos_sonoros"))
                mc.world.playSound("ld_eb.fire_elemental.3", entity.location, { pitch: 1, volume: 20 });

            const tick = mc.system.runInterval(() => {
                if (!spell.isValid() || ifDead(entity)) {
                    spell.remove();
                    return mc.system.clearRun(tick);
                }
                lib.getEntities(spell, 6).filter(e => e !== entity).forEach(async e => {
                    e.runCommand("fill ~~~ ~~~ fire replace air");
                    await mc.system.waitTicks(1);
                    e.runCommand("fill ~2~2~2 ~-2~-2~-2 air replace fire");
                    e.applyDamage(entityType.skills[this.index].damagePS*difficultyDamageController);
                    lib.middleImpulse(e, spell, -1, 0.4);
                });
            });

            await mc.system.waitTicks(10);
            spell.remove();

            await mc.system.waitTicks(Math.max(4, 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
    }
];

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");
});

mc.world.afterEvents.projectileHitBlock.subscribe(async data => {
    const entity = data.projectile;
    if (entity.typeId !== "ld_eb:ld_eb_fire_chain") return;

    const locator = lib.locator(entity);
    const owner = entity.owner;

    for (let i = 1; i <= 7; i++) {
        entity.dimension.spawnParticle(`ld_eb:fire_mobin_ferno_chain_${i}`, entity.location);
    }

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

    const tick = mc.system.runInterval(async () => {
        if (!locator.isValid()) return mc.system.clearRun(tick);
        lib.getEntities(locator, 10).filter(e => e !== owner).forEach(async e => {
            e.runCommand("fill ~~~ ~~~ fire replace air");
            await mc.system.waitTicks(1);
            e.runCommand("fill ~2~2~2 ~-2~-2~-2 air replace fire");
            e.applyDamage(entityType.skills[1].damagePS);
        });
    });

    entity.remove();
    await mc.system.waitTicks(40);
    locator.remove();
});

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