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


export function initDoor() {

    
    const
        chance = 1 / 29, 
        forebodingCheck = fo.scoreChapter4, 
        forebodingCheck7 = fo.scoreChapter7s, 
        interval = 4920, 
        CHECKINTERVAL = 1350, 

        overworld = fo.overworld;

    let
        eventflag = false, 
        eventflag2 = false; 


    
    const DOOR_LIST_PROPERTY = "door_locations";

    
    const woodenDoors = fo.doorIds;

    
    const copperDoor = fo.copperDoorIds;

    
    function openRandomDoor(players, minDistance) {
        const doorLocations = JSON.parse(world.getDynamicProperty(DOOR_LIST_PROPERTY) || "[]");

        if (!Array.isArray(doorLocations) || doorLocations.length === 0) {
            return; 
        }

        if (!Array.isArray(players)) {
            return; 
        }

        
        
        
        
        const
            furtherThanDistance = minDistance,
            withinDistance = 32,
            lookingForOpen = true, 
            validDoors = pickValidDoors(doorLocations, players, furtherThanDistance, withinDistance, lookingForOpen);

        if (validDoors.length === 0) return; 

        
        const randomDoor = pickValidRandomDoor(validDoors, doorLocations);
        if (!randomDoor) return; 

        const dimension = world.getDimension(randomDoor.dimensionId);
        const block = dimension.getBlock(randomDoor);

        
        const doorPermutation = block.permutation.withState("open_bit", true);
        block.setPermutation(doorPermutation);
        

        eventflag = false

        
        if (copperDoor.includes(block.typeId)) {
            dimension.playSound("open_door.copper", block.location, { volume: 2 });
        } else {
            dimension.playSound("random.door_open", block.location, { volume: 2 });
        }
    }

    
    function closeRandomDoor(players, minDistance) {
        const doorLocations = JSON.parse(world.getDynamicProperty(DOOR_LIST_PROPERTY) || "[]");

        if (!Array.isArray(doorLocations) || doorLocations.length === 0) {
            return; 
        }

        if (!Array.isArray(players)) {
            return; 
        }

        
        
        
        
        const
            furtherThanDistance = minDistance,
            withinDistance = 32,
            lookingForOpen = false, 
            validDoors = pickValidDoors(doorLocations, players, furtherThanDistance, withinDistance, lookingForOpen);

        if (validDoors.length === 0) return; 

        
        const randomDoor = pickValidRandomDoor(validDoors, doorLocations);
        if (!randomDoor) return; 

        const dimension = world.getDimension(randomDoor.dimensionId);
        const block = dimension.getBlock(randomDoor);

        
        const doorPermutation = block.permutation.withState("open_bit", false); 
        block.setPermutation(doorPermutation);
        

        eventflag = false

        
        if (copperDoor.includes(block.typeId)) {
            dimension.playSound("close_door.copper", block.location, { volume: 2 });
        } else {
            dimension.playSound("random.door_close", block.location, { volume: 2 });
        }
    }

    
    function hitRandomDoor(players, minDistance) {
        const doorLocations = JSON.parse(world.getDynamicProperty(DOOR_LIST_PROPERTY) || "[]");

        if (!Array.isArray(doorLocations) || doorLocations.length === 0) {
            return; 
        }

        if (!Array.isArray(players)) {
            return; 
        }

        
        
        
        
        const
            furtherThanDistance = minDistance,
            withinDistance = 32,
            lookingForOpen = true, 
            validDoors = pickValidDoors(doorLocations, players, furtherThanDistance, withinDistance, lookingForOpen);

        if (validDoors.length === 0) return; 

        
        const randomDoor = pickValidRandomDoor(validDoors, doorLocations);
        if (!randomDoor) return; 

        const dimension = world.getDimension(randomDoor.dimensionId);
        const block = dimension.getBlock(randomDoor);

        eventflag2 = false

        let doorDelay = 0;
        let totalHits = 1 + Math.floor(Math.random() * 4);

        
        for (let i = 0; i < totalHits; i++) {
            doorDelay = doorDelay + 8 + Math.floor(Math.random() * 8);

            system.runTimeout(() => {
                dimension.playSound("mob.zombie.wood", block.location, { volume: 3 });
            }, doorDelay)

        }


    }

    
    system.runInterval(() => {
        if (!eventflag && fo.forebodingScore >= forebodingCheck && Math.random() <= (chance * fo.netProbabilityModifier)) {
            eventflag = true;
        };

        if (!eventflag2 && fo.forebodingScore >= forebodingCheck && Math.random() <= (chance * fo.netProbabilityModifier)) {
            eventflag2 = true;
        };

    }, interval);


    
    system.runInterval(() => {

        
        if (eventflag) {
            const minDistance = 6 
            const players = world.getAllPlayers();
            openRandomDoor(players, minDistance);
        }

        
        if (eventflag2) {
            const minDistance = 20 
            const players = world.getAllPlayers();
            hitRandomDoor(players, minDistance);
        }

        
        if (fo.forebodingScore <= forebodingCheck7) {

            let doorDelay = 0;
            let tickCounter = 0;

            const minDistance = 2 
            const players = overworld.getPlayers();
            const totalRuns = players.length * 20;

            
            for (let i = 0; i < totalRuns; i++) {
                doorDelay = doorDelay + Math.floor(CHECKINTERVAL / totalRuns) - 1;
                tickCounter = Math.floor(Math.random() * 100);

                if (tickCounter % 2 === 0) {
                    system.runTimeout(() => openRandomDoor(players, minDistance), doorDelay);
                } else {
                    system.runTimeout(() => closeRandomDoor(players, minDistance), doorDelay);
                }

            }

        }

    }, CHECKINTERVAL);









    

    
    function getDistance(pos1, pos2) {
        if (!pos1 || !pos2) {
            return Infinity; 
        }
        return Math.sqrt(
            Math.pow(pos1.x - pos2.x, 2) +
            Math.pow(pos1.y - pos2.y, 2) +
            Math.pow(pos1.z - pos2.z, 2)
        );
    };

    
    function pickValidDoors(doorLocations, players, furtherThanDistance, withinDistance, lookingForOpen) {

        return doorLocations.filter(doorPos => {
            
            const playersInSameDimension = players.filter(player =>
                player.dimension.id === doorPos.dimensionId
            );

            if (playersInSameDimension.length === 0) {
                return false; 
            }

            
            const isNearPlayer = playersInSameDimension.some(player => {
                const distance = getDistance(player.location, doorPos);
                return distance <= withinDistance;
            });

            
            const isFarFromAllPlayers = playersInSameDimension.every(player => {
                const distance = getDistance(player.location, doorPos);
                return distance >= furtherThanDistance;
            });

            
            const dimension = world.getDimension(doorPos.dimensionId);
            const block = dimension.getBlock(doorPos);
            if (!block || !woodenDoors.includes(block.typeId)) {
                return false; 
            }

            
            const isClosed = !block.permutation.getState("open_bit"); 
            const doorStateMatches = !lookingForOpen ? !isClosed : isClosed; 

            return isNearPlayer && isFarFromAllPlayers && doorStateMatches;
        });

    };

    
    function pickValidRandomDoor(validDoors, doorLocations) {
        if (validDoors.length === 0) return null;

        const randomDoor = validDoors[Math.floor(Math.random() * validDoors.length)];
        const dimension = world.getDimension(randomDoor.dimensionId);
        const block = dimension.getBlock(randomDoor);

        
        if (!block || !woodenDoors.includes(block.typeId)) {
            removeDoorFromList(randomDoor, doorLocations);
            return null;
        }

        
        const isUpperBlock = block.permutation.getState("upper_block_bit");
        if (isUpperBlock) {
            removeDoorFromList(randomDoor, doorLocations);
            return null;
        }

        return randomDoor;
    };

    
    function removeDoorFromList(door, doorLocations) {
        const updatedLocations = doorLocations.filter(loc =>
            !(loc.x === door.x &&
                loc.y === door.y &&
                loc.z === door.z &&
                loc.dimensionId === door.dimensionId)
        );
        world.setDynamicProperty(DOOR_LIST_PROPERTY, JSON.stringify(updatedLocations));
        

    };

}