import { EntityEquippableComponent, EquipmentSlot, Player, system, world } from "@minecraft/server";
export class EquippableItem {
    // Constructor to initialize the EquippableItem class
    constructor(config) {
        this.config = config;
    }
    static registerBehavior(config) {
        const chargeBehavior = new EquippableItem(config);
        this.items.push(chargeBehavior);
    }
    static getItem(id) {
        return this.items.find((f) => f.config.id == id);
    }
    static initialize() {
        system.runInterval(() => {
            system.runJob(this.equippableTick());
        }, this.tickInterval);
        world.afterEvents.playerJoin.subscribe((data) => {
            const player = world.getEntity(data.playerId);
            if (!player)
                return;
            for (const slot of this.EquipmentSlots)
                player.setDynamicProperty(`cc.equippable.${slot}`, undefined);
        });
        world.afterEvents.entityHurt.subscribe((data) => {
            if (data.hurtEntity instanceof Player) {
                const equipComp = data.hurtEntity.getComponent(EntityEquippableComponent.componentId);
                if (!equipComp)
                    return;
                for (const slotId of this.EquipmentSlots) {
                    const slot = equipComp.getEquipmentSlot(slotId);
                    const item = slot.getItem();
                    if (!item)
                        continue;
                    const itemData = this.getItem(item.typeId);
                    if (!itemData || !itemData.config.onHurt)
                        continue;
                    itemData.config.onHurt(data);
                }
            }
            else if (data.damageSource.damagingEntity instanceof Player) {
                const player = data.damageSource.damagingEntity;
                const equipComp = player.getComponent(EntityEquippableComponent.componentId);
                if (!equipComp)
                    return;
                for (const slotId of this.EquipmentSlots) {
                    const slot = equipComp.getEquipmentSlot(slotId);
                    const item = slot.getItem();
                    if (!item)
                        continue;
                    const itemData = this.getItem(item.typeId);
                    if (!itemData || !itemData.config.onAttack)
                        continue;
                    itemData.config.onAttack({ source: player, hurtEntity: data.hurtEntity, damage: data.damage, damageSource: data.damageSource });
                }
            }
        });
    }
    static addEffects(player, effects) {
        for (const effect of effects)
            player.addEffect(effect.id, effect.duration, effect.options);
    }
    static removeEffects(player, effects) {
        for (const effect of effects)
            try {
                player.removeEffect(effect);
            }
            catch { }
    }
    static *equippableTick() {
        for (const player of world.getAllPlayers()) {
            const equippable = player.getComponent(EntityEquippableComponent.componentId);
            if (!equippable)
                continue;
            for (const slotId of this.EquipmentSlots) {
                const lastEquippedItem = player.getDynamicProperty(`cc.equippable.${slotId}`);
                const slot = equippable.getEquipmentSlot(slotId);
                const item = slot.getItem();
                player.setDynamicProperty(`cc.equippable.${slotId}`, item?.typeId);
                if (lastEquippedItem) {
                    const lastEquippedItemData = this.getItem(lastEquippedItem);
                    if (lastEquippedItemData) {
                        if (slotId == lastEquippedItemData.config.equipmentSlot && lastEquippedItemData.config.onUnequip && (!item || item.typeId != lastEquippedItem)) {
                            const unequip = lastEquippedItemData.config.onUnequip;
                            if (unequip.code)
                                unequip.code(player);
                            if (unequip.removeEffects)
                                this.removeEffects(player, unequip.removeEffects);
                        }
                    }
                }
                if (!item)
                    continue;
                const itemData = this.getItem(item.typeId);
                if (!itemData || itemData.config.equipmentSlot != slotId)
                    continue;
                const itemId = item.typeId;
                if (itemId != lastEquippedItem) {
                    if (itemData.config.onEquip) {
                        const equip = itemData.config.onEquip;
                        if (equip.code)
                            equip.code(player);
                        if (equip.addEffects)
                            this.addEffects(player, equip.addEffects);
                    }
                    if (itemData.config.onInterval) {
                        let active = true;
                        const onInterval = itemData.config.onInterval;
                        function intervalTick() {
                            if (!player || !player.isValid())
                                return;
                            if (!active)
                                return;
                            if (onInterval.code)
                                onInterval.code(player);
                            if (onInterval.addEffects)
                                EquippableItem.addEffects(player, onInterval.addEffects);
                            if (onInterval.removeEffects)
                                EquippableItem.removeEffects(player, onInterval.removeEffects);
                            system.runTimeout(() => {
                                intervalTick();
                            }, (onInterval.tickDelay == undefined || onInterval.tickDelay <= 0) ? 1 : onInterval.tickDelay);
                        }
                        intervalTick();
                        function activeTick() {
                            if (!player || !player.isValid())
                                return;
                            if (!active)
                                return;
                            const equippedItem = player.getDynamicProperty(`cc.equippable.${slotId}`);
                            if (equippedItem != itemId) {
                                active = false;
                                return;
                            }
                            system.runTimeout(() => {
                                activeTick();
                            }, EquippableItem.tickInterval);
                        }
                        activeTick();
                    }
                }
            }
        }
    }
}
EquippableItem.items = [];
EquippableItem.tickInterval = 20;
EquippableItem.EquipmentSlots = [
    EquipmentSlot.Head,
    EquipmentSlot.Chest,
    EquipmentSlot.Legs,
    EquipmentSlot.Feet,
    EquipmentSlot.Mainhand,
    EquipmentSlot.Offhand
];
