import { world, system } from "@minecraft/server";
import {
    namespace,
    BouldraxAttack1Damage,

    BouldraxAttack2Damage,
    BouldraxAttack2KnockbackStrength,

    BouldraxAttack3Damage,
    BouldraxAttack3Range,
    BouldraxAttack3KnockbackStrength
} from './config';

system.afterEvents.scriptEventReceive.subscribe((event) => {
    const entity = event.sourceEntity;

    if (event.id === `${namespace}:BouldraxAttack_1`) {
        attack1(entity);
    } else if (event.id === `${namespace}:BouldraxAttack_2`) {
        attack2(entity);
    } else if (event.id === `${namespace}:BouldraxAttack_3`) {
        attack3(entity);
    }
});

function attack1(entity) {
    if (!entity.isValid()) return;
    entity.triggerEvent("bunnystudios_rpg:attack_1");

    system.runTimeout(() => {
        if (!entity.isValid()) return;
        entity.runCommandAsync(`execute as @s at @s positioned ^^^5 run camerashake add @a[r=10] 0.1 1.5 positional`);
    }, 9);

    system.runTimeout(() => {
        if (!entity.isValid()) return;
        const pos = entity.location;
        const viewDirection = entity.getViewDirection();
        const damageCenter = {
            x: pos.x + (viewDirection.x * 3),
            y: pos.y + 1,
            z: pos.z + (viewDirection.z * 3)
        };
        const nearbyEntities = entity.dimension.getEntities({
            location: damageCenter,
            maxDistance: 5,
            excludeTypes: [entity.typeId, "item", "minecraft:snowball", "minecraft:arrow", "minecraft:xp_orb"],
            excludeFamilies: ["inanimate"]
        });
        const damage = entity.getProperty("bunnystudios_rpg:phase") === 2 ? BouldraxAttack1Damage * 2 : BouldraxAttack1Damage;
        for (const target of nearbyEntities) {
            target.applyDamage(damage, { cause: 'entityAttack', damagingEntity: entity });
        }
    }, 11);
}

function attack2(entity) {
    if (!entity.isValid()) return;
    entity.triggerEvent("bunnystudios_rpg:attack_2");

    system.runTimeout(() => {
        if (!entity.isValid()) return;
        let hits = 0;

        function hitEnemies() {
            if (!entity.isValid()) return;
            const pos = entity.location;
            const angle = entity.getRotation().y * (Math.PI / 180);

            hitArea(entity, pos, { start: 1, width: 10, length: 8 }, angle);
            hitArea(entity, pos, { start: 9, width: 22, length: 7 }, angle);

            hits++;
            if (hits < 9) {
                system.runTimeout(hitEnemies, 9);
            }
        }

        hitEnemies();
    }, 30);
}

function hitArea(entity, pos, area, angle) {
    if (!entity.isValid()) return;
    const centerX = pos.x - Math.sin(angle) * (area.start + area.length / 2);
    const centerZ = pos.z + Math.cos(angle) * (area.start + area.length / 2);

    const targets = entity.dimension.getEntities({
        location: { x: centerX, y: pos.y, z: centerZ },
        maxDistance: Math.max(area.width, area.length),
        excludeTypes: [entity.typeId, "item", "minecraft:snowball", "minecraft:arrow", "minecraft:xp_orb"],
        excludeFamilies: ["inanimate"]
    });

    const sin = Math.sin(angle);
    const cos = Math.cos(angle);

    targets.forEach(target => {
        if (target.id === entity.id) return;

        const targetPos = target.location;
        const dx = targetPos.x - pos.x;
        const dz = targetPos.z - pos.z;

        const rotX = dx * cos + dz * sin;
        const rotZ = -dx * sin + dz * cos;

        if (rotZ >= area.start &&
            rotZ <= area.start + area.length &&
            Math.abs(rotX) <= area.width / 2) {
            const damage = entity.getProperty("bunnystudios_rpg:phase") === 2 ? BouldraxAttack2Damage * 2 : BouldraxAttack2Damage;

            target.applyDamage(damage, { cause: 'entityAttack', damagingEntity: entity });

            const dist = Math.sqrt(dx * dx + dz * dz);
            if (dist > 0) {
                target.applyKnockback(
                    dx / dist,
                    dz / dist,
                    BouldraxAttack2KnockbackStrength * 3,
                    BouldraxAttack2KnockbackStrength * 0.5
                );
            }
        }
    });
}

function attack3(entity) {
    if (!entity.isValid()) return;
    entity.triggerEvent("bunnystudios_rpg:attack_3");

    system.runTimeout(() => {
        if (!entity.isValid()) return;
        const pos = entity.location;
        const targets = entity.dimension.getEntities({
            location: pos,
            excludeFamilies: ["inanimate"],
            maxDistance: BouldraxAttack3Range,
            excludeTypes: [entity.typeId, "item", "minecraft:snowball", "minecraft:arrow", "minecraft:xp_orb"]
        });

        targets.forEach(target => {
            const dx = target.location.x - pos.x;
            const dz = target.location.z - pos.z;
            const damage = entity.getProperty("bunnystudios_rpg:phase") === 2 ? BouldraxAttack3Damage * 2 : BouldraxAttack3Damage;
            target.applyDamage(damage, { cause: 'entityAttack', damagingEntity: entity });
            target.applyKnockback(
                dx,
                dz,
                BouldraxAttack3KnockbackStrength * 2,
                BouldraxAttack3KnockbackStrength * 0.5
            );
        });

        system.runTimeout(() => {
            if (!entity.isValid()) return;
            let hits = 0;
            const damageLoop = system.runInterval(() => {
                if (!entity.isValid() || hits >= 3) {
                    system.clearRun(damageLoop);
                    return;
                }

                const nearTargets = entity.dimension.getEntities({
                    location: entity.location,
                    excludeFamilies: ["inanimate"],
                    maxDistance: 16,
                    excludeTypes: [entity.typeId, "item", "minecraft:snowball", "minecraft:arrow", "minecraft:xp_orb"]
                });
                const damage = entity.getProperty("bunnystudios_rpg:phase") === 2 ? BouldraxAttack3Damage * 2 : BouldraxAttack3Damage;

                nearTargets.forEach(target => {
                    target.applyDamage(damage, { cause: 'entityAttack', damagingEntity: entity });
                });

                hits++;
            }, 12);
        }, 20);
    }, 14);
}