import { system, world, Player, Entity, MolangVariableMap, EntityComponentTypes } from "@minecraft/server";
import { GauntletManager } from "./gauntletClasses.js";
import { staticEffectMethods, sparksEffectMethods, stunEffectMethods } from "../entities/commonEntityMethods.js";


// ASSIGN GAUNTLET MANAGER TO PLAYER
Object.assign(Player.prototype, {
    gauntletManager: null,
    initializeGauntletManager() {
        this.gauntletManager = new GauntletManager(this);
    }
});


// SET UP ENTITIES
Object.assign(Entity.prototype, staticEffectMethods);
Object.assign(Entity.prototype, sparksEffectMethods);
Object.assign(Entity.prototype, stunEffectMethods);

world.afterEvents.entityLoad.subscribe((event) => {
    try {
        event.entity?.staticEffectOnLoad();
        event.entity?.sparksEffectOnLoad();
        event.entity?.stunEffectOnLoad();
    } catch (e) {
        //console.error(`§cError in entityLoad: ${e}`);
    }
});

function isPlayerWithNecroGauntlet(player) {
    return player instanceof Player &&
        player?.gauntletManager?.getEquipedGauntletTypeId() === "oct_eg:necro_gauntlet";
}
function spawnSoulAtLocation(entity) {
    const spawnLoc = {
        x: entity.location.x,
        y: entity.location.y + 0.2,
        z: entity.location.z
    }
    const randomDir = {
        x: (Math.random() - 0.5) * 0.5,
        y: 0.4,
        z: (Math.random() - 0.5) * 0.5
    }
    const soul = entity.dimension.spawnEntity("oct_eg:soul", spawnLoc);
    soul.applyImpulse(randomDir);

}
world.afterEvents.entityDie.subscribe(e => {
    try {

        const killedEntity = e.deadEntity;
        const damager = e.damageSource?.damagingEntity;

        if (!killedEntity.isValid()
            || killedEntity.typeId === "oct_eg:undead_minion"
            || killedEntity?.getComponent(EntityComponentTypes.Tameable)?.tamedToPlayer === damager
        ) return;

        //world.sendMessage(`Entity died: ${killedEntity.typeId} | Damager: ${damager?.typeId} | Projectile: ${projectile?.typeId}`);
        if (!damager) return;

        let necroKillReason = null;
        // 1. Directly by player with gauntlet
        if (isPlayerWithNecroGauntlet(damager)) {
            necroKillReason = "player";
        }
        // 2. Tamed entity of a player with gauntlet
        if (!necroKillReason) {
            const tamedOwner = damager?.getComponent(EntityComponentTypes.Tameable)?.tamedToPlayer ?? undefined;
            if (tamedOwner && isPlayerWithNecroGauntlet(tamedOwner)) {
                necroKillReason = "tamed entity";
            }
        }
        // If any valid necro kill reason was found, spawn the soul
        if (necroKillReason) {
            //world.sendMessage(`§2DEBUG: KILLED BY NECRO (${necroKillReason})`);
            spawnSoulAtLocation(killedEntity);
        }

    } catch (e) { }

}); // FIXME: No idea how to get the damaging projectile


// ANIMATION INITIALIZATION
function detectPlayerRotationChange(player) {
    //console.info('§8DEBUG: RUN CHECK');
    const currRot = player.getRotation();
    const prevRotData = player.getDynamicProperty("oct_eg:prevRot");
    const prevRot = prevRotData ? JSON.parse(prevRotData) : currRot;

    player.setDynamicProperty("oct_eg:prevRot", JSON.stringify(currRot));

    return currRot.x !== prevRot.x || currRot.y !== prevRot.y;
}
function checkIfClientReady(player) {
    if (player.getDynamicProperty("oct_eg:clientReady")) return; // Already initialized
    if (!detectPlayerRotationChange(player)) return; // Wait for rotation change
    player.setDynamicProperty("oct_eg:clientReady", true);
    //console.info('§gDEBUG: CLIENT LOADED');
}

// CLEANUP
world.beforeEvents.playerLeave.subscribe(event => {
    if (!event.player) return;

    system.run(() => {
        // Cancel any active attacks
        event.player?.gauntletManager?.cancelActiveAttack();

        // Usubscribe player listeners
        event.player?.gauntletManager?.unsubscribeEventListeners();
    })
    event.player.setDynamicProperty("oct_eg:clientReady", undefined);
    event.player.setDynamicProperty("oct_eg:prevRot", undefined);
})
world.afterEvents.entityDie.subscribe(event => {
    if (!event.deadEntity || !(event.deadEntity instanceof Player)) return;

    system.run(() => {
        // Cancel any active attacks
        if (event.deadEntity?.gauntletManager) event.deadEntity.gauntletManager?.cancelActiveAttack();
    })

}, { entityTypes: ["minecraft:player"] })

// TICK LOGIC
system.runInterval(() => {
    for (const player of world.getPlayers()) {

        if (!player.gauntletManager) player.initializeGauntletManager(); // Initialize gauntlet manager if it doesn't exist
        player.gauntletManager.tick();

        checkIfClientReady(player);
    }
}, 1);

if (world.getDynamicProperty("oct_eg:pvpDamageScallingPercent") === undefined) {
    //console.info("§2PVP DAMAGE SCALLING PERCENT SET TO 100%");
    world.setDynamicProperty("oct_eg:pvpDamageScallingPercent", 50);
};

// Tamed Wolf Edgecase
world.beforeEvents.playerInteractWithEntity.subscribe(e => {
    const tamed = e.target;
    if (tamed.hasComponent(EntityComponentTypes.Tameable)) {
        system.runTimeout(() => {
            if (!tamed.hasComponent(EntityComponentTypes.Tameable))
                tamed.setDynamicProperty("oct_eg:owner_id", e.player.id);
        }, 2)
    }
})

/*
world.beforeEvents.playerBreakBlock.subscribe(event => {
    if (!event.player) return;
    if (event.player?.gauntletManager?.equippedGauntlet) event.cancel = true;
})
*/