import { world, system } from "@minecraft/server";
import { fo } from './utilities/fo_constants.js';





export function initStare() {

    
    const CHANCE = 1 / 300; 
    const SCORE_MIN = fo.scoreChapter5 + (fo.durationChapter5 * 0.79);
    const SCORE_MID = fo.scoreChapter5 + (fo.durationChapter5 * 0.90);
    const SCORE_MAX = fo.scoreChapter5 + (fo.durationChapter5 * 0.9992);
    const FOV = 180;
    const MAX_MOBS_PER_TICK = 50;

    const mobTypes = new Set([
        "minecraft:cow", "minecraft:chicken", "minecraft:frog", "minecraft:mooshroom",
        "minecraft:ocelot", "minecraft:pig", "minecraft:rabbit", "minecraft:sheep",
        "minecraft:villager", "minecraft:villager_v2", "minecraft:wandering_trader",
        "minecraft:sniffer", "minecraft:armadillo", "minecraft:fox", "minecraft:goat",
        "minecraft:llama", "minecraft:panda", "minecraft:trader_llama"
    ]);

    let eventSingle = false;
    let eventActive = false;
    let eventPhase2 = false;
    let stareInterval = null;
    let SingleStareInterval = null;
    let tickPlayerIndex = 0;

    const processedMobs = new Set();


    function angleBetween(v1, v2) {
        const dot = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
        const mag1 = Math.sqrt(v1.x ** 2 + v1.y ** 2 + v1.z ** 2);
        const mag2 = Math.sqrt(v2.x ** 2 + v2.y ** 2 + v2.z ** 2);
        return Math.acos(dot / (mag1 * mag2)) * (FOV / Math.PI);
    }

    function freezeMob(entity) {
        try {
            const movement = entity.getComponent("minecraft:movement");
            if (!movement || movement.currentValue !== movement.defaultValue) return;
            movement.setCurrentValue(0);
        } catch { }
    }

    function unfreezeMob(entity) {
        try {
            const movement = entity.getComponent("minecraft:movement");
            if (!movement || movement.currentValue === movement.defaultValue) return;
            movement.resetToDefaultValue();
        } catch { }
    }

    function* processMobStaring(player) {
        const pos = player.location;
        const view = player.getViewDirection();
        const dimension = player.dimension;

        const entities = dimension.getEntities({ location: pos, maxDistance: 64 });
        let processedCount = 0;

        for (const entity of entities) {
            try {
                if (processedCount >= MAX_MOBS_PER_TICK) break;
                if (!mobTypes.has(entity.typeId)) continue;
                if (processedMobs.has(entity.id)) continue;

                const dx = entity.location.x - pos.x;
                const dy = entity.location.y - pos.y;
                const dz = entity.location.z - pos.z;
                const distSq = dx * dx + dy * dy + dz * dz;

                const inRadius = distSq <= 15 * 15;

                const dir = { x: dx, y: dy, z: dz };
                const mag = Math.sqrt(distSq);
                const norm = { x: dx / mag, y: dy / mag, z: dz / mag };
                const inFOV = angleBetween(view, norm) <= FOV / 2;

                if (!inRadius && !inFOV) continue;

                const closestPlayer = dimension.getPlayers({
                    location: entity.location,
                    maxDistance: 64,
                    closest: 1,
                })[0];

                if (!closestPlayer) continue;

                entity.lookAt(closestPlayer.location);
                if (!eventPhase2) freezeMob(entity);
                processedMobs.add(entity.id);
                processedCount++;
            } catch (e) { console.warn(`Error ${e} at handling mob stare`) }
            yield;
        }
    }

    function startMobStare() {
        if (stareInterval !== null) return;

        stareInterval = system.runInterval(() => {
            processedMobs.clear();

            const players = fo.overworld.getPlayers();
            if (players.length === 0) return;

            const player = players[tickPlayerIndex % players.length];
            system.runJob(processMobStaring(player));

            tickPlayerIndex++;
        }, 2); 
    }

    function stopMobStare() {
        if (stareInterval !== null) {
            system.clearRun(stareInterval);
            stareInterval = null;
            tickPlayerIndex = 0;
        }
    }

    function recoverFrozenMobsNear(player, radius = 60) {
        const dimension = player.dimension;
        const pos = player.location;
        const nearbyEntities = dimension.getEntities({ location: pos, maxDistance: radius });

        for (const entity of nearbyEntities) {
            if (!mobTypes.has(entity.typeId)) continue;
            unfreezeMob(entity);
        }
    }

    function cowScreams() {
        const SOUND = "fo_mob.ghast.scream";
        const SOUND_VOLUME = 4;
        const SOUND_PITCH = 0.3;
        const SOUND_MIN_DELAY = 1;
        const SOUND_MAX_DELAY = 120;
        const MAX_COWS = 3;

        
        const cows = fo.overworld.getEntities({
            type: "minecraft:cow"
        });

        
        const shuffled = cows.sort(() => Math.random() - 0.5).slice(0, MAX_COWS);

        for (const cow of shuffled) {
            const delay = Math.floor(Math.random() * (SOUND_MAX_DELAY - SOUND_MIN_DELAY + 1)) + SOUND_MIN_DELAY;

            system.runTimeout(() => {
                try {
                    const loc = cow.location;
                    const dim = cow.dimension;
                    dim.playSound(SOUND, loc, {
                        volume: SOUND_VOLUME,
                        pitch: SOUND_PITCH
                    });
                } catch (e) {
                    
                }
            }, delay);
        }
    }

    function singleMobStaring() {
        const cow = fo.overworld.getEntities({
            type: "minecraft:cow",
        })[0];
        if (!cow) {
            system.runTimeout(singleMobStaring, 6003);
            return;
        }

        

        freezeMob(cow);

        SingleStareInterval = system.runInterval(() => {
            try {
                if (!cow) return;

                const dimension = cow.dimension;
                const player = dimension.getPlayers({
                    location: cow.location,
                    closest: 1,
                })[0];

                if (!player) return;

                cow.lookAt(player.location);

                const close = dimension.getPlayers({
                    location: cow.location,
                    maxDistance: 6,
                    closest: 1,
                });

                if (close.length > 0 || eventActive) {
                    system.clearRun(SingleStareInterval);
                    eventSingle = false;
                    unfreezeMob(cow);
                    

                }

            } catch (e) {
                
                eventSingle = false;
                system.clearRun(SingleStareInterval);
            }
        }, 1)
    }


    
    system.runInterval(() => {
        const score = fo.forebodingScore;
        if (!eventActive && !eventSingle && Math.random() <= CHANCE) {
            singleMobStaring();
            eventSingle = true;
        };
        if (score >= SCORE_MIN && score <= SCORE_MAX) {
            if (!eventActive) {
                startMobStare();
                eventActive = true;
            };
            if (eventActive && score >= SCORE_MID && !eventPhase2) {
                eventPhase2 = true;
                cowScreams();

            }
        } else if (eventActive) {
            stopMobStare();
            eventActive = false;
            eventPhase2 = false;
        }
    }, 60); 

    
    system.runInterval(() => {
        if (!eventSingle && !eventActive || eventPhase2) {
            const players = fo.overworld.getPlayers();
            for (const player of players) {
                recoverFrozenMobsNear(player);
            }
        }
    }, 1218); 

}