import {
    EntityComponentTypes,
    EntityHealthComponent,
    EntityTameableComponent,
    EntityTypeFamilyComponent,
    Player,
    system,
    world,
} from "@minecraft/server";
import { Bosses } from "../data/bosses";
import { DynamicProperties } from "../data/dynamic_properties";
import { Entities } from "../data/entities";
import { NegativePotionEffects } from "../data/potion_effects";
import { Menus } from "../menus/menus";
import {
    attackSequence,
    getRandomBetween,
    isBoss,
    knockbackEntity,
    shootProjectile,
    startItemCooldownAfterUse,
} from "../utils/utils";

world.beforeEvents.worldInitialize.subscribe((event) => {
    //WEAPONS
    const clown_hammer = event.itemComponentRegistry.registerCustomComponent("ns_rh:clown_hammer", {
        onUse: (iEvent) => {
            const { source: player, itemStack: item } = iEvent;

            const skillDamage = 15;
            startItemCooldownAfterUse(player, item, () => {
                const hitEntity = player.getEntitiesFromViewDirection({ maxDistance: 4 })[0];
                const viewDirection = player.getViewDirection();
                const knockbackHorizontalStrength = 1.8;
                const knockbackVerticalStrength = 0.6;

                knockbackEntity(
                    player,
                    skillDamage,
                    knockbackHorizontalStrength,
                    knockbackVerticalStrength,
                    {
                        affectPlayers: false,
                    }
                );
            });
        },
    });
    const scissor_blade = event.itemComponentRegistry.registerCustomComponent(
        "ns_rh:scissor_blade",
        {
            onUse: (iEvent) => {
                const { source: player, itemStack: item } = iEvent;

                const attacks = [
                    {
                        damage: 3,
                        effects: [
                            {
                                effectType: "poison",
                                duration: 1,
                                amplifier: 0,
                            },
                        ],
                        callback: () => {},
                        delay: 0,
                    },
                    {
                        damage: 3,
                        effects: [],

                        callback: () => {},
                        delay: 0.5,
                    },
                    {
                        damage: 3,
                        effects: [],
                        callback: () => {},
                        delay: 0.5,
                    },
                ];

                startItemCooldownAfterUse(player, item, () => {
                    if (player.isSneaking) {
                        attackSequence(player, attacks);
                    } else {
                        //Projetil...
                        shootProjectile(player, "ns_rh:scissor", {
                            power: 5.0,
                            gravity: 0.001,
                            sound: "item.trident.throw",
                        });
                    }
                });
            },
        }
    );
    const lich_scythe = event.itemComponentRegistry.registerCustomComponent("ns_rh:lich_scythe", {
        onUse: (iEvent) => {
            const { source: player, itemStack: item } = iEvent;

            const mobs = Entities;

            startItemCooldownAfterUse(player, item, () => {
                if (player.isSneaking) {
                    //Summon random mob

                    const entitiesArray = Object.values(Entities).filter(
                        (e) => !isBoss(e.typeId, Bosses)
                    );

                    const randomMob =
                        entitiesArray[getRandomBetween(0, entitiesArray.length - 1)].typeId;

                    const entity = player.dimension.spawnEntity(randomMob, {
                        x: player.location.x + getRandomBetween(-2, 2),
                        y: player.location.y,
                        z: player.location.z + getRandomBetween(-2, 2),
                    });

                    if (!isBoss(entity.typeId, Bosses)) {
                        entity.triggerEvent("self:tameable");

                        entity.triggerEvent("self:ressurected_spawned");

                        entity.nameTag = "Companion";

                        entity.addTag("summoned");

                        system.runTimeout(() => {
                            /**
                             * @type {EntityTameableComponent}
                             */
                            const tameable = entity.getComponent(EntityComponentTypes.Tameable);

                            /**
                             * @type {EntityHealthComponent}
                             */
                            const healthComponent = entity.getComponent(
                                EntityComponentTypes.Health
                            );

                            if (healthComponent) {
                                const maxHealth = healthComponent.effectiveMax;

                                healthComponent.setCurrentValue(maxHealth / 2);
                            }

                            if (tameable) {
                                tameable.tame(player);
                            }
                        }, 0.1 * 20);
                    }
                } else {
                    //Projetil...
                    shootProjectile(player, "ns_rh:lich_skull", {
                        offset: {
                            x: 0,
                            y: 1.6,
                            z: 0,
                        },
                        gravity: 0.001,
                        sound: "mob.blaze.shoot",
                        power: 3.0,
                    });
                }
            });
        },
    });

    //SPELL BOOKS
    const summon_dolls = event.itemComponentRegistry.registerCustomComponent("ns_rh:summon_dolls", {
        onUse: (iEvent) => {
            const { source: player, itemStack: item } = iEvent;

            startItemCooldownAfterUse(player, item, () => {
                const entityCount = 4;
                const entityType = "ns_rh:madre_doll";

                player.playSound("mob.evocation_illager.cast_spell", {
                    volume: 100,
                    pitch: 1,
                });

                player.spawnParticle("ns_rh:summon_dolls", player.location);

                for (let c = 0; c < entityCount; c++) {
                    const topmostBlock = player.dimension.getTopmostBlock({
                        x: player.location.x,
                        z: player.location.z,
                    });

                    const doll = player.dimension.spawnEntity(entityType, {
                        x: player.location.x + getRandomBetween(-3, 3),
                        y: topmostBlock?.location.y + 1,
                        z: player.location.z + getRandomBetween(-3, 3),
                    });

                    doll.triggerEvent("self:tameable");

                    doll.triggerEvent("self:ressurected_spawned");

                    doll.nameTag = "Companion";

                    doll.addTag("summoned");

                    system.runTimeout(() => {
                        /**
                         * @type {EntityTameableComponent}
                         */
                        const tameable = doll.getComponent(EntityComponentTypes.Tameable);

                        if (tameable) {
                            tameable.tame(player);
                        }
                    }, 0.1 * 20);
                }
            });
        },
    });

    const fear = event.itemComponentRegistry.registerCustomComponent("ns_rh:fear", {
        onUse: (iEvent) => {
            const { source: player, itemStack: item } = iEvent;

            const effects = [
                {
                    effectType: "slowness",
                    duration: 15,
                    amplifier: 1,
                },
                {
                    effectType: "weakness",
                    duration: 15,
                    amplifier: 0,
                },
            ];

            startItemCooldownAfterUse(player, item, () => {
                const nearbyEntities = player.dimension.getEntities({
                    location: player.location,
                    maxDistance: 10,
                });

                player.playSound("mob.evocation_illager.cast_spell", {
                    volume: 100,
                    pitch: 1,
                });

                player.spawnParticle("ns_rh:fear", player.location);

                for (let entity of nearbyEntities) {
                    /**
                     * @type {EntityTypeFamilyComponent}
                     */
                    const typeFamily = entity.getComponent(EntityComponentTypes.TypeFamily);

                    if (entity instanceof Player) {
                        if (entity != player) {
                            //...
                        }
                    } else {
                        if (typeFamily) {
                            if (!typeFamily.hasTypeFamily("companion")) {
                                for (let effect of effects) {
                                    entity.addEffect(effect.effectType, effect.duration * 20, {
                                        amplifier: effect.amplifier,
                                        showParticles: false,
                                    });
                                }
                            }
                        }
                    }
                }
            });
        },
    });

    const vampiric_mark = event.itemComponentRegistry.registerCustomComponent(
        "ns_rh:vampiric_mark",
        {
            onUse: (iEvent) => {
                const { source: player, itemStack: item } = iEvent;

                startItemCooldownAfterUse(player, item, () => {
                    const nearbyEntities = player.dimension.getEntities({
                        location: player.location,
                        maxDistance: 8,
                    });

                    player.playSound("mob.evocation_illager.cast_spell", {
                        volume: 100,
                        pitch: 1,
                    });

                    player.spawnParticle("ns_rh:vampiric_mark", player.location);

                    for (let entity of nearbyEntities) {
                        /**
                         * @type {EntityTypeFamilyComponent}
                         */
                        const typeFamily = entity.getComponent(EntityComponentTypes.TypeFamily);

                        if (entity instanceof Player) {
                            if (entity != player) {
                                //...
                            }
                        } else {
                            if (typeFamily) {
                                if (!typeFamily.hasTypeFamily("companion")) {
                                    entity.setDynamicProperty(
                                        DynamicProperties.vampiric_mark,
                                        true
                                    );

                                    if (entity.nameTag == "") {
                                        entity.nameTag = "§4Marked";
                                    } else {
                                        const currentNameTag = entity.nameTag;

                                        entity.nameTag = `${currentNameTag} §4Marked`;
                                    }
                                }
                            }
                        }
                    }
                });
            },
        }
    );

    const rejection = event.itemComponentRegistry.registerCustomComponent("ns_rh:rejection", {
        onUse: (iEvent) => {
            const { source: player, itemStack: item } = iEvent;

            startItemCooldownAfterUse(player, item, () => {
                player.playSound("mob.evocation_illager.cast_spell", {
                    volume: 100,
                    pitch: 1,
                });

                player.spawnParticle("ns_rh:rejection", player.location);

                player.setDynamicProperty(DynamicProperties.spell_rejection, true);
            });
        },
    });

    const grace_period = event.itemComponentRegistry.registerCustomComponent("ns_rh:grace_period", {
        onUse: (iEvent) => {
            const { source: player, itemStack: item } = iEvent;

            startItemCooldownAfterUse(player, item, () => {
                player.playSound("mob.evocation_illager.cast_spell", {
                    volume: 100,
                    pitch: 1,
                });

                player.spawnParticle("ns_rh:grace", player.location);

                player.setDynamicProperty(DynamicProperties.spell_grace_period, true);

                for (let effect of NegativePotionEffects) {
                    if (player.getEffect(effect)) {
                        player.removeEffect(effect);
                    }
                }
            });
        },
    });

    const lich_spellbook = event.itemComponentRegistry.registerCustomComponent(
        "ns_rh:lich_spellbook",
        {
            onUse: (iEvent) => {
                const { source: player, itemStack: item } = iEvent;

                startItemCooldownAfterUse(player, item, () => {
                    Menus.lich_spellbook(player, item);
                });
            },
        }
    );

    const configurator = event.itemComponentRegistry.registerCustomComponent("ns_rh:configurator", {
        onUse: (iEvent) => {
            const { source: player, itemStack: item } = iEvent;

            Menus.configurations(player);
        },
    });

    const cursed_summon_relic = event.itemComponentRegistry.registerCustomComponent(
        "ns_rh:cursed_summon_relic",
        {
            onUse: (iEvent) => {
                const { source: player, itemStack: item } = iEvent;

                const playerLocation = player.location;

                Menus.coliseum_teleport_warn(player);

                /**
                 * @type {EntityEquippableComponent}
                 */
                /*  const equippableComponent = player.getComponent(EntityComponentTypes.Equippable);

                startItemCooldownAfterUse(player, item, () => {
                    equippableComponent.setEquipment(EquipmentSlot.Mainhand);

                    const playerViewDirection = player.getViewDirection();

                    const getSpawnHeigth =
                        playerLocation.y + 100 < player.dimension.heightRange.max - 32
                            ? playerLocation.y + 100
                            : player.dimension.heightRange.max - 32;

                    const structure = world.structureManager.place(
                        "ns_rh:coliseum",
                        player.dimension,
                        {
                            x: playerLocation.x - 16,
                            y: getSpawnHeigth,
                            z: playerLocation.z - 16,
                        }
                    );

                    const playerSpawnLocation = {
                        x: playerLocation.x,
                        y: getSpawnHeigth + 7,
                        z: playerLocation.z,
                    };

                    system.runTimeout(() => {
                        player.teleport(playerSpawnLocation);
                    }, 5 * 20);
                }); */
            },
        }
    );

    //....
});

world.afterEvents.itemUse.subscribe((event) => {
    const { itemStack, source: player } = event;

    switch (itemStack.typeId) {
        case "ns_rh:lich_spellbookaa": {
            /**
             * @type {ItemCooldownComponent}
             */
            const cooldown = itemStack?.getComponent("minecraft:cooldown");

            if (cooldown) {
                const cooldownTicks = cooldown?.cooldownTicks;
                const remainingCooldown = cooldown?.getCooldownTicksRemaining(player);

                if (remainingCooldown == cooldownTicks - 1) {
                    Menus.lich_spellbook(player, itemStack);
                }

                break;
            }
        }
    }
});
