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


export function initAfk() {

    world.setDynamicProperty("afkPause", false); 

    let
        playerTracking = new Map(),
        afkPause = false,
        stareCooldown = 60;

    const
        scoreChapter3 = fo.scoreChapter3,
        scoreChapter4 = fo.scoreChapter4,
        scoreChapter5 = fo.scoreChapter5,
        afkEventChance = 1 / 3;


    function runRandomEvent(player) {
        if (Math.random() < 0.7) playRandomNoises(player);
        else doorOpenCloses(player);
    };

    system.runInterval(() => {
        const forebodingScore = fo.forebodingScore;

        if (forebodingScore !== -1) {

            const players = world.getPlayers();
            let totalPlayers = players.length;
            let currentTime = Date.now(); 

            for (const player of players) {
                let playerId = player.id; 
                let currentPos = player.location;
                let currentView = player.getViewDirection();

                
                if (!currentView) {
                    continue;
                }

                
                if (!playerTracking.has(playerId)) {
                    playerTracking.set(playerId, { sessionStartTime: currentTime, lastPos: currentPos, lastView: currentView, idleTime: 0 });
                    continue;
                }

                let playerData = playerTracking.get(playerId);

                
                let sessionDuration = currentTime - playerData.sessionStartTime;
                if (sessionDuration < 5000) {
                    playerTracking.set(playerId, { ...playerData, idleTime: 0 }); 
                    continue;
                }

                
                if (
                    playerData.lastPos.x !== currentPos.x ||
                    playerData.lastPos.y !== currentPos.y ||
                    playerData.lastPos.z !== currentPos.z ||
                    playerData.lastView?.x !== currentView.x ||  
                    playerData.lastView?.y !== currentView.y ||
                    playerData.lastView?.z !== currentView.z
                ) {
                    if (playerData.idleTime >= 60) {
                        world.setDynamicProperty("afkPause", false);
                        afkPause = false;

                        if (playerData.idleTime >= 200) {
                            player.runCommand(`execute in overworld run fog @s[r=99999999] remove Fog`); 
                            player.runCommand(`execute in overworld run fog @s[r=99999999] remove FogF`);
                            player.runCommand(`execute in overworld run fog @s[r=99999999] remove FogR`);

                            const forebodingObj = fo.forebodingObjective;
                            forebodingObj.setScore(player, 0);
                        }

                        if (playerData.idleTime >= 900) {
                            player.stopMusic();

                            system.runTimeout(() => {
                                if (forebodingScore > fo.scoreChapter3) player.playMusic("forefeelM", { volume: 0.01, loop: true });
                                if (forebodingScore < fo.scoreChapter7s) player.playMusic("phurpa", { volume: 0.01, loop: true });
                                
                            }, 1)
                        }

                    }
                    playerTracking.set(playerId, { lastPos: currentPos, lastView: currentView, idleTime: 0 });
                    continue;
                }

                
                
                
                playerData.idleTime++;

                if (playerData.idleTime === 200) {
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter3}.. run fog @s[y=31,dy=600,r=99999999] push "foreboding:fog01r" FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter3}.. run fog @s[y=30,dy=-200,r=99999999] push "foreboding:fog01ru" FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter3}.. run fog @s[y=31,dy=600,r=99999999] push "foreboding:fog01f" FogF`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter3}.. run fog @s[y=30,dy=-200,r=99999999] push "foreboding:fog01fu" FogF`);
                } else if (playerData.idleTime === 300) {
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter3}.. run fog @s[r=99999999] remove FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter3}.. run fog @s[r=99999999] remove FogF`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter3}.. run fog @s[y=31,dy=600,r=99999999] push "foreboding:fog02r" FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter3}.. run fog @s[y=30,dy=-200,r=99999999] push "foreboding:fog02ru" FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter3}.. run fog @s[y=31,dy=600,r=99999999] push "foreboding:fog08f" FogF`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter3}.. run fog @s[y=30,dy=-200,r=99999999] push "foreboding:fog08fu" FogF`);
                } else if (playerData.idleTime === 500) {
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter4}.. run fog @s[r=99999999] remove FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter4}.. run fog @s[r=99999999] remove FogF`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter4}.. run fog @s[y=31,dy=600,r=99999999] push "foreboding:fog03r" FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter4}.. run fog @s[y=30,dy=-200,r=99999999] push "foreboding:fog03ru" FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter4}.. run fog @s[y=31,dy=600,r=99999999] push "foreboding:fog09f" FogF`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter4}.. run fog @s[y=30,dy=-200,r=99999999] push "foreboding:fog09fu" FogF`);
                    if (Math.random() < afkEventChance / 2) runRandomEvent(player);
                } else if (playerData.idleTime === 600) {
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter4}.. run fog @s[r=99999999] remove FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter4}.. run fog @s[r=99999999] remove FogF`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter4}.. run fog @s[y=31,dy=600,r=99999999] push "foreboding:fog04r" FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter4}.. run fog @s[y=30,dy=-200,r=99999999] push "foreboding:fog04ru" FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter4}.. run fog @s[y=31,dy=600,r=99999999] push "foreboding:fog10f" FogF`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter4}.. run fog @s[y=30,dy=-200,r=99999999] push "foreboding:fog10fu" FogF`);
                    if (Math.random() < afkEventChance) runRandomEvent(player);
                } else if (playerData.idleTime === 700) {
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter5}.. run fog @s[r=99999999] remove FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter5}.. run fog @s[r=99999999] remove FogF`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter5}.. run fog @s[y=31,dy=600,r=99999999] push "foreboding:fog05r" FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter5}.. run fog @s[y=30,dy=-200,r=99999999] push "foreboding:fog05ru" FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter5}.. run fog @s[y=31,dy=600,r=99999999] push "foreboding:fog11f" FogF`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter5}.. run fog @s[y=30,dy=-200,r=99999999] push "foreboding:fog11fu" FogF`);
                    if (Math.random() < afkEventChance * 1.5) runRandomEvent(player);
                } else if (playerData.idleTime === 800) {
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter5}.. run fog @s[r=99999999] remove FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter5}.. run fog @s[r=99999999] remove FogF`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter5}.. run fog @s[y=31,dy=600,r=99999999] push "foreboding:fog06r" FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter5}.. run fog @s[y=30,dy=-200,r=99999999] push "foreboding:fog06ru" FogR`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter5}.. run fog @s[y=31,dy=600,r=99999999] push "foreboding:fog12f" FogF`);
                    player.runCommand(`execute in overworld unless score "Counter " Foreboding matches ${scoreChapter5}.. run fog @s[y=30,dy=-200,r=99999999] push "foreboding:fog12fu" FogF`);
                    if (Math.random() < afkEventChance * 2) runRandomEvent(player);
                } else if (playerData.idleTime === 900) {
                    player.runCommand(`execute in overworld run fog @s[r=99999999] remove FogR`);
                    player.runCommand(`execute in overworld run fog @s[r=99999999] remove FogF`);
                    player.runCommand(`execute in overworld run fog @s[y=31,dy=600,r=99999999] push "foreboding:fog07" FogR`);
                    player.runCommand(`execute in overworld run fog @s[y=30,dy=-200,r=99999999] push "foreboding:fog07u" FogR`);
                    runRandomEvent(player);
                    player.playMusic("fo_whispers", { fade: 10, volume: 0.1, loop: true });
                } else if (playerData.idleTime === 1000) {
                    player.runCommand(`execute in overworld run fog @s[r=99999999] remove FogR`);
                    player.runCommand(`execute in overworld run fog @s[r=99999999] remove FogF`);
                    player.runCommand(`execute in overworld run fog @s[y=31,dy=600,r=99999999] push "foreboding:fog08" FogR`);
                    player.runCommand(`execute in overworld run fog @s[y=30,dy=-200,r=99999999] push "foreboding:fog08U" FogR`);
                    player.playMusic("fo_whispers", { fade: 10, volume: 0.2, loop: true });
                } else if (playerData.idleTime === 1100) {
                    player.playMusic("fo_whispers", { fade: 10, volume: 0.3, loop: true });
                }

                
                if (totalPlayers === 1 && playerData.idleTime >= 60 && !afkPause) {
                    world.setDynamicProperty("afkPause", true)

                    afkPause = true

                }

                
                if (totalPlayers > 1 && playerData.idleTime >= 300 && stareCooldown <= 0 && forebodingScore > scoreChapter3) {
                    const nearbyPlayers = player.dimension.getPlayers({
                        excludeNames: [player.name],
                        location: player.location,
                        maxDistance: 16,
                    });
                    if (nearbyPlayers.length > 0) {
                        let isInSight;
                        for (const p of players) {
                            isInSight = islookingAtPlayer(p, player,);
                            if (isInSight) break;
                        }
                        if (!isInSight) {
                            player.lookAt(nearbyPlayers[0].location);
                            system.runTimeout(() => { playerData.lastView = player.getViewDirection() }, 1)
                        }
                    }

                }


                stareCooldown <= 0 ? stareCooldown = 60 : stareCooldown--;
                playerTracking.set(playerId, playerData);
            }

        }

    }, 60); 



    
    function islookingAtPlayer(player, afkPlayer) {
        const playerPos = player.location;
        const afkPos = afkPlayer.location;

        const playerViewDir = player.getViewDirection();

        
        const afkPlayerDir = {
            x: afkPos.x - playerPos.x,
            y: afkPos.y - playerPos.y,
            z: afkPos.z - playerPos.z
        };

        
        const afkPlayerDirLength = Math.sqrt(afkPlayerDir.x ** 2 + afkPlayerDir.y ** 2 + afkPlayerDir.z ** 2);
        const normalizedAfkPlayerDir = {
            x: afkPlayerDir.x / afkPlayerDirLength,
            y: afkPlayerDir.y / afkPlayerDirLength,
            z: afkPlayerDir.z / afkPlayerDirLength
        };

        
        const dotProduct = playerViewDir.x * normalizedAfkPlayerDir.x +
            playerViewDir.y * normalizedAfkPlayerDir.y +
            playerViewDir.z * normalizedAfkPlayerDir.z;

        
        const angle = Math.acos(dotProduct);

        
        const fovThreshold = (60 * Math.PI) / 180;

        
        return angle <= fovThreshold;
    }

};
