import { EntityHealthComponent, system, world, EntityEquippableComponent, ItemDurabilityComponent, ItemStack, EquipmentSlot, EntityInventoryComponent } from "@minecraft/server";

const functions = {
    damageWeapon(item, damage) {
        const durability = item?.getComponent(ItemDurabilityComponent.componentId);

        if (!durability) return item;
        durability.damage += damage;
        return item;
    },
    getEquipmentComponent(entity) {
        return entity.getComponent(EntityEquippableComponent.componentId);
    },
    getWeapon(player, offhand = false) {
        return this.getEquipmentComponent(player)
            .getEquipment(offhand ? EquipmentSlot.Offhand : EquipmentSlot.Mainhand);
    },
    calculateReduction(damage, damager, isProyectile = false) {
        if (isProyectile) return damage;
        return damage - (damage * 0.3);
    },
    findWeapon(player) {
        return [false, true]
            .map(offhand => this.getWeapon(player, offhand))
            .filter(item => item?.typeId.includes("broadsword"))[0];
    }
}

const protectedPlayers = new Map();

system.runInterval(async () => {
    for (const player of world.getPlayers()) {
        const weapon = functions.findWeapon(player);

        if (functions.getWeapon(player, true)?.typeId == "minecraft:shield") continue;
        if (!(weapon && player.isSneaking)) {
            protectedPlayers.delete(player.nameTag);
            continue
        } else if (!protectedPlayers.get(player.nameTag)) protectedPlayers.set(player.nameTag, weapon);
        player.addEffect("weakness", 5, { amplifier: 255, showParticles: false });
        player.playAnimation("animation.player.sword_blocking");
    }
});

world.afterEvents.entityHurt.subscribe(event => {
    const { hurtEntity: player, damage, damageSource: source } = event;
    const { damagingEntity: entity, damagingProjectile: projectile } = source;
    const protectedPlayer = protectedPlayers.get(player.nameTag);

    if (!protectedPlayer) return;
    const healthComponent = player.getComponent(EntityHealthComponent.componentId);
    const reduction = functions.calculateReduction(damage, entity || projectile, !!projectile);

    player.playSound('sword.block');
    functions.damageWeapon(player, protectedPlayer);
    player.teleport(player.location);
    system.run(() => {
        healthComponent.setCurrentValue(healthComponent.currentValue + reduction);
    });
}, { entityTypes: ["minecraft:player"] });


system.beforeEvents.watchdogTerminate.subscribe(ev => ev.cancel = true);

world.beforeEvents.itemUse.subscribe((arg) => {
    const { itemStack } = arg;
    const source = arg.source;
    if (itemStack?.typeId !== "fiery:totem_of_undying" && itemStack?.typeId !== "minecraft:totem_of_undying" && itemStack?.typeId !== "minecraft:shield") {
        return;
    }
    system.run(() => {
        const offhand = source.getComponent("minecraft:equippable");
        const offhandItem = offhand?.getEquipment(EquipmentSlot.Offhand);
        const container = source?.getComponent("minecraft:inventory")?.container;
        const mainhand = container.getSlot(source.selectedSlot);
        const mainhandItem = container.getItem(source.selectedSlot);
        if (mainhandItem?.typeId !== itemStack.typeId) {
            return;
        }
        offhand.setEquipment(EquipmentSlot.Offhand, mainhandItem);
        source.playSound("armor.equip_generic");
        source.playAnimation("animation.player.swipe_item");
        mainhand.setItem(offhandItem);
    });
});

