import { EntityComponentTypes, EntityDamageCause, Player, system, world } from "@minecraft/server";

import { executeRandomizedMove, knockbackEntity } from "../utils/utils";

const bosses = ["pixell_bbo:hades"];

world.afterEvents.entityHurt.subscribe((event) => {
    const { damage, damageSource, hurtEntity } = event;

    const damagingEntity = damageSource?.damagingEntity;

    if (!damagingEntity) return;

    if (damageSource && damageSource?.damagingEntity?.typeId == "pixell_bbo:hades") {
        const variant = damagingEntity.getComponent(EntityComponentTypes.Variant);

        if (variant?.value == 0) {
            system.runTimeout(() => {
                const dimension = damagingEntity?.dimension;

                if (!dimension) return;

                const damagingEntityIsLoaded = dimension.getEntities().includes(damagingEntity);

                const hurtEntityIsLoaded = dimension.getEntities().includes(hurtEntity);

                if (!damagingEntityIsLoaded || !hurtEntityIsLoaded) return;

                knockbackEntity(damagingEntity, hurtEntity, 8, 0.6);
            }, 1.3 * 20);
        }

        const targetPropName = "ninja:target";

        const targetProp = damagingEntity.getDynamicProperty(targetPropName);

        if (!targetProp) {
            damagingEntity.setDynamicProperty(targetPropName, hurtEntity.id);

            return;
        }

        damagingEntity.setDynamicProperty(targetPropName, hurtEntity.id);
    }

    if (hurtEntity.typeId == "pixell_bbo:hades") {
        /**
         * @type {number | undefined}
         */
        const stage = hurtEntity.getProperty("self:stage");

        if (stage == 1 || stage == 2) {
            /**
             * @type {number | undefined}
             */
            const hitsTaken = hurtEntity.getProperty("self:hits_taken");

            if (hitsTaken == undefined) return;

            if (hitsTaken >= 4) {
                hurtEntity.triggerEvent("self:teleport");

                return;
            }

            hurtEntity.setProperty("self:hits_taken", Math.min(4, hitsTaken + 1));
        }
    }

    if (damageSource?.damagingEntity?.typeId == "minecraft:player") {
        const consecutivesAttacks = damageSource?.damagingEntity?.getDynamicProperty(
            "pixell_bbo:consecutivesAttacks"
        );

        if (consecutivesAttacks == undefined) {
            damageSource?.damagingEntity?.setDynamicProperty("pixell_bbo:consecutivesAttacks", 0);
        }

        if (bosses.includes(hurtEntity.typeId)) {
            if (hurtEntity.getProperty("self:attack_type") == "melee") {
                if (
                    hurtEntity.getProperty("self:attacks") == "basic" ||
                    hurtEntity.getProperty("self:attacks") == "none"
                ) {
                    damageSource?.damagingEntity?.setDynamicProperty(
                        "pixell_bbo:consecutivesAttacks",
                        consecutivesAttacks + 1
                    );

                    if (consecutivesAttacks >= 3) {
                        system.runTimeout(() => {
                            const teleportDistance = 6;

                            hurtEntity.addEffect("invisibility", 0.5 * 20, {
                                amplifier: 1,
                                showParticles: false,
                            });

                            const dashPower = 3;

                            hurtEntity.applyImpulse({
                                x:
                                    hurtEntity.location.x < damageSource?.damagingEntity?.location.x
                                        ? dashPower
                                        : -dashPower,
                                y: damageSource?.damagingEntity?.location.y,
                                z:
                                    hurtEntity.location.z < damageSource?.damagingEntity?.location.z
                                        ? dashPower
                                        : -dashPower,
                            });

                            hurtEntity.triggerEvent("self:attack_anim");

                            damageSource?.damagingEntity?.applyDamage(1, {
                                damagingEntity: hurtEntity,
                                cause: EntityDamageCause.entityAttack,
                            });
                        }, 0.45 * 20);

                        damageSource?.damagingEntity?.setDynamicProperty(
                            "pixell_bbo:consecutivesAttacks",
                            0
                        );
                    } else if (
                        hurtEntity.getProperty("self:attacks") != "basic" &&
                        hurtEntity.getProperty("self:attacks") != "none"
                    ) {
                        damageSource?.damagingEntity?.setDynamicProperty(
                            "pixell_bbo:consecutivesAttacks",
                            0
                        );
                    }
                }
            }
        }
    } else if (bosses.includes(damageSource?.damagingEntity?.typeId)) {
        if (hurtEntity.typeId == "minecraft:player") {
            hurtEntity.setDynamicProperty("pixell_bbo:consecutivesAttacks", 0);

            system.runTimeout(() => {
                if (!damageSource?.damagingEntity?.hasTag("pixell_bbo:dying")) {
                    hurtEntity.applyDamage(1, {
                        cause: EntityDamageCause.entityAttack,
                    });
                }
            }, 0.6 * 20);

            system.runTimeout(() => {
                if (!damageSource?.damagingEntity?.hasTag("pixell_bbo:dying")) {
                    hurtEntity.applyDamage(1, {
                        cause: EntityDamageCause.entityAttack,
                    });
                }
            }, 1.24 * 20);

            system.runTimeout(() => {
                if (!damageSource?.damagingEntity?.hasTag("pixell_bbo:dying")) {
                    hurtEntity.applyDamage(1, {
                        cause: EntityDamageCause.entityAttack,
                    });
                }
            }, 1.8 * 20);
        }
    }
});

world.afterEvents.projectileHitEntity.subscribe((event) => {
    const { source, projectile } = event;

    const entity = event.getEntityHit().entity;

    if (bosses.includes(entity.typeId)) {
        if (projectile.typeId.includes("arrow")) {
            const consecutivesArrowAttacks = source?.getDynamicProperty(
                "pixell_bbo:consecutivesArrowAttacks"
            );

            if (consecutivesArrowAttacks == undefined) {
                source.setDynamicProperty("pixell_bbo:consecutivesArrowAttacks", 0);
            }

            if (entity.getProperty("self:stage") == 2) {
                source.setDynamicProperty(
                    "pixell_bbo:consecutivesArrowAttacks",
                    consecutivesArrowAttacks + 1
                );

                if (consecutivesArrowAttacks >= 6) {
                    system.runTimeout(() => {
                        entity.addEffect("invisibility", 0.5 * 20, {
                            amplifier: 1,
                            showParticles: false,
                        });

                        const dashPower = 4;

                        entity.applyImpulse({
                            x: hurtEntity.location.x < source.location.x ? dashPower : -dashPower,
                            y: 0.2,
                            z: hurtEntity.location.z < source.location.z ? dashPower : -dashPower,
                        });

                        entity.triggerEvent("self:underworld_sphere");

                        entity.dimension.spawnEntity("pixell_bbo:underworld_sphere", {
                            x: entity.location.x,
                            y: entity.location.y + 12,
                            z: entity.location.z,
                        });
                    }, 0.45 * 20);

                    source.setDynamicProperty("pixell_bbo:consecutivesArrowAttacks", 0);
                }
            }
        }
    }
});

const Phase1Moves = new Map([
    [
        "teleport",
        {
            weight: 10,
            duration: 2.0,
            properties: [
                {
                    name: "self:attacks",
                    value: "none",
                },
            ],
            event: "self:teleport",
            time_down_event: "self:reset_attacks",
        },
    ],
    [
        "fire_ball",
        {
            weight: 8,
            duration: 2.0,
            properties: [
                {
                    name: "self:attacks",
                    value: "fire_ball",
                },
            ],
            event: "self:fire_ball",
            time_down_event: "self:reset_attacks",
        },
    ],
    [
        "hell_curse",
        {
            weight: 10,
            duration: 2.0,
            properties: [
                {
                    name: "self:attacks",
                    value: "hell_curse",
                },
            ],
            event: "self:hell_curse",
            time_down_event: "self:reset_attacks",
        },
    ],
    [
        "summon",
        {
            weight: 8,
            duration: 2.0,
            properties: [
                {
                    name: "self:attacks",
                    value: "summon",
                },
            ],
            event: "self:summon_mode",
            time_down_event: "self:reset_attacks",
        },
    ],
    [
        "ressurection",
        {
            weight: 2,
            duration: 2.0,
            properties: [
                {
                    name: "self:attacks",
                    value: "ressurection",
                },
            ],
            event: "self:ressurection",
            time_down_event: "self:reset_attacks",
        },
    ],
]);

const Phase2Moves = new Map([
    [
        "teleport",
        {
            weight: 10,
            duration: 2.0,
            properties: [
                {
                    name: "self:attacks",
                    value: "none",
                },
            ],
            event: "self:teleport",
            time_down_event: "self:reset_attacks",
        },
    ],
    [
        "fire_ball",
        {
            weight: 8,
            duration: 2.0,
            properties: [
                {
                    name: "self:attacks",
                    value: "fire_ball",
                },
            ],
            event: "self:fire_ball",
            time_down_event: "self:reset_attacks",
        },
    ],
    [
        "hell_curse",
        {
            weight: 10,
            duration: 2.0,
            properties: [
                {
                    name: "self:attacks",
                    value: "hell_curse",
                },
            ],
            event: "self:hell_curse",
            time_down_event: "self:reset_attacks",
        },
    ],
    [
        "orb",
        {
            weight: 5,
            duration: 2.0,
            properties: [
                {
                    name: "self:attacks",
                    value: "orb",
                },
            ],
            event: "self:orb",
            time_down_event: "self:reset_attacks",
        },
    ],
    [
        "underworld_arc",
        {
            weight: 5,
            duration: 2.0,
            properties: [
                {
                    name: "self:attacks",
                    value: "underworld_arc",
                },
            ],
            event: "self:underworld_arc",
            time_down_event: "self:reset_attacks",
        },
    ],
    [
        "underworld_fire",
        {
            weight: 5,
            duration: 2.0,
            properties: [
                {
                    name: "self:attacks",
                    value: "underworld_fire",
                },
            ],
            event: "self:underworld_fire",
            time_down_event: "self:reset_attacks",
        },
    ],
    [
        "summon",
        {
            weight: 8,
            duration: 2.0,
            properties: [
                {
                    name: "self:attacks",
                    value: "summon",
                },
            ],
            event: "self:summon_mode",
            time_down_event: "self:reset_attacks",
        },
    ],
    [
        "ressurection",
        {
            weight: 2,
            duration: 2.0,
            properties: [
                {
                    name: "self:attacks",
                    value: "ressurection",
                },
            ],
            event: "self:ressurection",
            time_down_event: "self:reset_attacks",
        },
    ],
]);

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

    try {
        if (bosses.includes(entity.typeId)) {
            let health = entity?.getComponent("health");

            if (eventId == "self:random_event") {
                const addedComponentGroup = event.getModifiers()[0].addedComponentGroups;

                const attackName = addedComponentGroup[0];

                if (attackName == "self:fire_ball") {
                }

                executeRandomizedMove(entity, Phase1Moves);
            }

            if (eventId == "self:hell_curse") {
                /**
                 * @type {Player[]}
                 */
                const players = entity.dimension.getPlayers({
                    location: entity.location,
                    maxDistance: 32,
                });

                for (let player of players) {
                    system.runTimeout(() => {
                        player.spawnParticle("pixell_bbo:spin_inclode", player.location);

                        player.spawnParticle("pixell_bbo:trail_cubic_hades", player.location);

                        player.spawnParticle("pixell_bbo:gorundfx", player.location);

                        player.applyKnockback(0, 0, 1, 0.8);

                        player.setOnFire(5, true);
                    }, 1.8 * 20);
                }
            }

            if (eventId == "self:summon_mode") {
                if (entity.getProperty("self:summon") == false) {
                    entity.setProperty("self:summon", true);
                } else {
                    entity.setProperty("self:summon", false);
                }
            }

            if (eventId == "self:switch_to_melee") {
            }

            if (eventId == "self:dying") {
                health.setCurrentValue(1);

                entity.addEffect("instant_health", 8 * 20, { showParticles: false, amplifier: 2 });

                entity.addTag("pixell_bbo:dying");
            }

            if (eventId == "self:second_form") {
                entity.removeTag("pixell_bbo:dying");
            }

            if (eventId == "self:switch_to_ranged") {
            }

            if (eventId == "self:ressurection") {
            }

            if (eventId == "self:default") {
                system.runTimeout(() => {
                    entity?.triggerEvent("self:basic_attack");
                }, 3 * 20);
            }

            if (eventId == "self:teleport") {
                const targetPropName = "ninja:target";

                const targetProp = entity?.getDynamicProperty(targetPropName);

                if (!targetProp) {
                    system.runTimeout(() => {
                        entity?.triggerEvent("self:reset_attacks");
                    }, 0.45 * 20);

                    return;
                }

                const targetEntity = entity.dimension.getEntities().find((e) => e.id == targetProp);

                if (!targetEntity) {
                    entity?.triggerEvent("self:reset_attacks");

                    return;
                }

                /*  entity.applyImpulse({
                x: entity.getViewDirection().x * 6,
                y: 0.2,
                z: entity.getViewDirection().z * 6,
            }); */

                //  teleportBehindTarget(entity, targetEntity);

                const dashPower = 3;

                entity.applyImpulse({
                    x: entity.location.x < targetEntity.location.x ? dashPower : -dashPower,
                    y: 0.2,
                    z: entity.location.z < targetEntity.location.z ? dashPower : -dashPower,
                });

                entity?.triggerEvent("self:reset_attacks");

                entity?.triggerEvent("self:random_event");
            }

            if (eventId == "self:random_event_phase_2") {
                const addedComponentGroup = event.getModifiers()[0].addedComponentGroups;

                const attackName = addedComponentGroup[0];

                executeRandomizedMove(entity, Phase2Moves);
            }

            if (eventId == "self:underworld_fire") {
                const players = entity.dimension.getPlayers({
                    location: entity.location,
                    maxDistance: 32,
                });

                for (let player of players) {
                    player.setOnFire(5);
                }

                system.runTimeout(() => {
                    entity?.triggerEvent("self:reset_attacks");
                }, 4 * 20);
            }

            if (eventId == "self:attack_anim") {
                system.runTimeout(() => {
                    entity?.triggerEvent("self:reset_attacks");
                }, 0.25 * 20);
            }
        }
    } catch (error) {}
});
