import { EntityDamageCause, Player, system, world } from "@minecraft/server";
import { Entities } from "./Entities";
import { movePlayerAway } from "../utils/utils";

const Attacks = [
    {
        time: 0.5,
        damage: 3,
    },
    {
        time: 0.75,
        damage: 3,
    },
    {
        time: 1.0,
        damage: 3,
    },
    {
        time: 1.25,
        damage: 3,
    },
];

const difficultyDamage = new Map([
    [
        "easy",
        {
            damage: 4,
        },
    ],
    [
        "normal",
        {
            damage: 6,
        },
    ],
    [
        "hard",
        {
            damage: 8,
        },
    ],
]);

world.afterEvents.dataDrivenEntityTrigger.subscribe((event) => {
    const { entity, eventId } = event;

    if (entity.typeId == Entities.pyro) {
        switch (eventId) {
            case "clown:attack_sequence": {
                sequenceAttack(entity);
                break;
            }
            case "clown:fire_attack": {
                flameThrow(entity);
                break;
            }
            case "clown:move_player_away": {
                movePlayerAway(entity, 1.7);
                break;
            }
        }
    }
});

/**
 *
 * @param {Entity} entity
 */
function sequenceAttack(entity) {
    const viewDirection = entity.getViewDirection();

    const dimension = entity.dimension;

    const attackRange = 3.5;

    const difficulty = entity.getProperty("clown:difficulty");

    const damage = difficultyDamage.get(difficulty).damage ?? 0;

    for (let attack = 0; attack < Attacks.length; attack++) {
        const { time } = Attacks[attack];

        if (entity) {
            system.runTimeout(() => {
                try {
                    const nearbyEntities =
                        dimension.getEntities({
                            location: {
                                x: entity?.location.x,
                                y: entity?.location.y,
                                z: entity?.location.z,
                            },
                            maxDistance: attackRange,
                        }) ?? [];

                    for (let mob of nearbyEntities) {
                        if (mob != entity) {
                            if (mob instanceof Player) {
                                if (entity.matches({ excludeFamilies: ["passive"] })) {
                                    mob?.setOnFire(5);
                                    mob?.applyDamage(damage, {
                                        cause: EntityDamageCause.entityAttack,
                                        damagingEntity: entity,
                                    });
                                }
                            } else {
                                mob?.setOnFire(5);
                                mob?.applyDamage(damage, {
                                    cause: EntityDamageCause.entityAttack,
                                    damagingEntity: entity,
                                });
                            }
                        }
                    }
                } catch (e) {}
            }, time * 20);
        }
    }
}

/**
 *
 * @param {Entity} entity
 */
function flameThrow(entity) {
    const viewDirection = entity.getViewDirection();

    const size = 8;

    const entities = entity.dimension.getEntities({
        location: {
            x: entity.location.x + viewDirection.x,
            y: entity.location.y,
            z: entity.location.z + viewDirection.z,
        },
        volume: {
            x: viewDirection.x * size,
            y: 2,
            z: viewDirection.z * size,
        },
        excludeTypes: ["minecraft:item", "minecraft:xp_orb"],
    });

    for (let mob of entities) {
        if (mob !== entity) {
            if (mob instanceof Player) {
                if (entity.matches({ excludeFamilies: ["passive"] })) {
                    mob?.setOnFire(5);
                }
            } else {
                mob?.setOnFire(5);
            }
        }
    }
}
