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


export function initNetherPortal() { 

    
    const
        mirrorWorldCenter = { x: 100272, y: 62, z: 100256 }, 

        CHANCE = 1 / 30, 
        FOREBODINGCHECK = fo.scoreChapter3, 
        FOREBODINGCHECK7 = fo.scoreChapter7,
        PORTAL_BREAK_CHECK_INTERVAL = 85, 
        PLAYER_DISTANCE_MIN = 42, 
        PLAYER_DISTANCE_MAX = 62, 

        nether = fo.nether,
        overworld = fo.overworld;

    
    nether.runCommand(`/tickingarea remove MWSpawnpoint`);
    overworld.runCommand(`/tickingarea remove MWSpawnpoint`);

    
    let isPortalBreakingActive = false;
    let targetPlayer = null;
    let portalLocation = null; 

    
    function getDistance(loc1, loc2) {
        const dx = loc1.x - loc2.x;
        const dy = loc1.y - loc2.y;
        const dz = loc1.z - loc2.z;
        return Math.sqrt(dx * dx + dy * dy + dz * dz);
    }

    
    function getBaseLocation() {
        const data = world.getDynamicProperty("base_location");
        return data ? JSON.parse(data) : null;
    }


    
    function isAreaClear(location) {
        for (const player of nether.getPlayers()) {
            const distance = getDistance(player.location, location);
            if (distance < PLAYER_DISTANCE_MIN) {
                return false; 
            }
        }
        return true; 
    }

    
    function breakPortal(location) {
        if (location) {
            const { x, y, z } = location;
            const
                explosionOptions = {
                    breaksBlocks: true,
                    causesFire: false,
                },
                soundOptions = {
                    volume: 4,
                    pitch: 0.9,
                };


            
            nether.playSound("mob.ghast.charge", location, soundOptions);

            
            system.runTimeout(() => { nether.createExplosion(location, 4, explosionOptions) }, 30);
            
        }
    }

    
    function mirrorWorldTeleport(player, spawnPos, dimension) {
        const isMirrorWorldTp = world.getDynamicProperty("mirrorWorldDoorTp");
        if (isMirrorWorldTp) {
            world.setDynamicProperty("mirrorWorldDoorTp", false);
            return;
        }

        let
            maxTpAttempts = 60,
            playerTeleported = false;

        for (let tpAttempt = 0; tpAttempt < maxTpAttempts; tpAttempt++) {
            system.runTimeout(() => {

                if (!playerTeleported) {
                    const
                        spawnBlock = dimension.getBlock(spawnPos);

                    

                    if (spawnBlock) {

                        const
                            spawnBlockAbove = spawnBlock.above(1),
                            spawnBlockAbove2 = spawnBlock.above(2);

                        if (spawnBlockAbove.isAir && spawnBlockAbove2.isAir) {

                            const DimensionLocation = {
                                dimension: dimension,
                                x: spawnBlockAbove.x,
                                y: spawnBlockAbove.y,
                                z: spawnBlockAbove.z,
                            };

                            player.teleport(spawnBlockAbove.location)

                            player.setSpawnPoint(DimensionLocation);

                        } else {
                            const
                                topMostblock = dimension.getTopmostBlock(spawnPos, dimension.heightRange.max - 1),
                                topMostblockAbove = topMostblock.above(1);

                            player.teleport(topMostblockAbove.location)

                            const DimensionLocation = {
                                dimension: dimension,
                                x: topMostblockAbove.x,
                                y: topMostblockAbove.y,
                                z: topMostblockAbove.z,
                            };

                            player.setSpawnPoint(DimensionLocation);
                            dimension.runCommand(`tickingarea remove MWSpawnpoint`);

                            playerTeleported = true;
                        }
                    }
                }
            }, tpAttempt * 2)
        }
    }

    
    world.afterEvents.playerDimensionChange.subscribe(({ player, fromDimension, toDimension }) => {
        const forebodingScore = fo.forebodingScore;

        
        if (forebodingScore >= FOREBODINGCHECK) {

            if (fromDimension.id === "minecraft:overworld" && toDimension.id === "minecraft:nether") {

                const probabilityModifier = Math.min(fo.netProbabilityModifier, 5);

                if (Math.random() < (CHANCE * probabilityModifier)) { 
                    isPortalBreakingActive = true;
                    targetPlayer = player;
                    

                    
                    portalLocation = { x: player.location.x, y: player.location.y + 2, z: player.location.z };
                    
                }
            }
        }


        
        if (forebodingScore < FOREBODINGCHECK7) {
            const mirrorBaseLocation = getBaseLocation();

            
            if (fromDimension.id === "minecraft:overworld" && toDimension.id === "minecraft:nether" && mirrorBaseLocation !== null) {
                nether.runCommand(`tickingarea add ${mirrorWorldCenter.x - 8} ${mirrorWorldCenter.y} ${mirrorWorldCenter.z - 8} ${mirrorWorldCenter.x + 8} ${mirrorWorldCenter.y} ${mirrorWorldCenter.z + 8} MWSpawnpoint true`);
                system.runTimeout(() => {

                    
                    mirrorWorldTeleport(player, mirrorWorldCenter, nether)

                }, 5)
            };

            
            if (fromDimension.id === "minecraft:nether" && toDimension.id === "minecraft:overworld" && mirrorBaseLocation !== null) {
                overworld.runCommand(`tickingarea add ${mirrorBaseLocation.x - 8} ${mirrorBaseLocation.y} ${mirrorBaseLocation.z - 8} ${mirrorBaseLocation.x + 8} ${mirrorBaseLocation.y} ${mirrorBaseLocation.z + 8} MWSpawnpoint true`);
                system.runTimeout(() => {

                    
                    mirrorWorldTeleport(player, mirrorBaseLocation, overworld)

                }, 5)
            }

        }


    });

    
    system.runInterval(() => {
        if (!isPortalBreakingActive || !targetPlayer || !portalLocation) return;

        
        if (targetPlayer.dimension.id === "minecraft:nether") {
            
            const distance = getDistance(targetPlayer.location, portalLocation);
            if (distance >= PLAYER_DISTANCE_MIN && distance <= PLAYER_DISTANCE_MAX) {
                
                if (isAreaClear(portalLocation)) {
                    breakPortal(portalLocation);
                    isPortalBreakingActive = false;
                    targetPlayer = null;
                    portalLocation = null; 
                } else {
                    
                }
            }
        }
    }, PORTAL_BREAK_CHECK_INTERVAL);

}
