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






export function initMossyPyramids() {
    const FOREBODINGCHECK = fo.scoreChapter2;
    const forebodingScore = fo.forebodingScore;

    if (forebodingScore >= FOREBODINGCHECK) {
        mainPyramidLogic();
    } else {
        system.runTimeout(initMossyPyramids, 1907);
    }
}


function mainPyramidLogic() {
    
    const
        overworld = fo.overworld,
        BASE_PLACE_INTERVAL = 2, 
        PLACE_INTERVAL = Math.max(1, Math.floor(BASE_PLACE_INTERVAL * Math.min(fo.performanceModifier, 3))),
        PROXIMITY_RADIUS = 256, 
        BASE_Y = 60;

    
    let
        saved = world.getDynamicProperty("mainPyramid"),
        progress = saved ? JSON.parse(saved) : {
            x: 7680,
            z: -1536,
            size: 95,
            height: 47,
            stage: "search", 
            currentY: -64,
            step: 0,
            paused: false,
            pausedx: 0,
            pausedy: 0,
            pausedz: 0,
            
            blocksSinceLastSave: 0,
            saveThreshold: fo.performanceModifier === 1 ? 2 : fo.performanceModifier === 1.5 ? 3 : fo.performanceModifier === 2.5 ? 4 : 5
        };

    

    if (progress.paused) system.runTimeout(mainPyramidLogic, 6001);

    
    const playerMadeBlocks = [
        "minecraft:acacia_door",
        "minecraft:acacia_door",
        "minecraft:acacia_fence",
        "minecraft:acacia_planks",
        "minecraft:bamboo_door",
        "minecraft:bamboo_fence",
        "minecraft:bamboo_planks",
        "minecraft:barrel",
        "minecraft:bed",
        "minecraft:birch_door",
        "minecraft:birch_door",
        "minecraft:birch_fence",
        "minecraft:birch_planks",
        "minecraft:cherry_door",
        "minecraft:cherry_fence",
        "minecraft:cherry_planks",
        "minecraft:chest",
        "minecraft:cobblestone",
        "minecraft:copper_door",
        "minecraft:crafting_table",
        "minecraft:crimson_door",
        "minecraft:crimson_door",
        "minecraft:crimson_fence",
        "minecraft:crimson_planks",
        "minecraft:dark_oak_door",
        "minecraft:dark_oak_door",
        "minecraft:dark_oak_fence",
        "minecraft:dark_oak_planks",
        "minecraft:exposed_copper_door",
        "minecraft:furnace",
        "minecraft:glass",
        "minecraft:white_stained_glass",
        "minecraft:orange_stained_glass",
        "minecraft:magenta_stained_glass",
        "minecraft:light_blue_stained_glass",
        "minecraft:yellow_stained_glass",
        "minecraft:lime_stained_glass",
        "minecraft:pink_stained_glass",
        "minecraft:gray_stained_glass",
        "minecraft:light_gray_stained_glass",
        "minecraft:cyan_stained_glass",
        "minecraft:purple_stained_glass",
        "minecraft:blue_stained_glass",
        "minecraft:brown_stained_glass",
        "minecraft:green_stained_glass",
        "minecraft:red_stained_glass",
        "minecraft:black_stained_glass",
        "minecraft:iron_door",
        "minecraft:jungle_door",
        "minecraft:jungle_door",
        "minecraft:jungle_fence",
        "minecraft:jungle_planks",
        "minecraft:lantern",
        "minecraft:lit_furnace",
        "minecraft:lit_redstone_lamp",
        "minecraft:mangrove_door",
        "minecraft:mangrove_door",
        "minecraft:mangrove_fence",
        "minecraft:mangrove_planks",
        "minecraft:nether_brick_fence",
        "minecraft:oak_fence",
        "minecraft:oak_planks",
        "minecraft:oxidized_copper_door",
        "minecraft:pale_oak_door",
        "minecraft:pale_oak_fence",
        "minecraft:pale_oak_planks",
        "minecraft:polished_diorite",
        "minecraft:polished_granite",
        "minecraft:redstone_lamp",
        "minecraft:spruce_door",
        "minecraft:spruce_door",
        "minecraft:spruce_fence",
        "minecraft:spruce_planks",
        "minecraft:stone_bricks",
        "minecraft:torch",
        "minecraft:warped_door",
        "minecraft:warped_door",
        "minecraft:warped_fence",
        "minecraft:warped_planks",
        "minecraft:waxed_copper_door",
        "minecraft:waxed_exposed_copper_door",
        "minecraft:waxed_oxidized_copper_door",
        "minecraft:waxed_weathered_copper_door",
        "minecraft:weathered_copper_door",
        "minecraft:wooden_door",
        "minecraft:wooden_door",
        "minecraft:blast_furnace",
        "minecraft:lit_blast_furnace",
        "minecraft:smoker",
        "minecraft:lit_smoker",
        "minecraft:redstone_wire",
        "minecraft:bookshelf",
        "minecraft:enchanting_table",
        "minecraft:brewing_stand",
        "minecraft:farmland",
        "minecraft:glass_pane",
        "minecraft:white_stained_glass_pane",
        "minecraft:orange_stained_glass_pane",
        "minecraft:magenta_stained_glass_pane",
        "minecraft:light_blue_stained_glass_pane",
        "minecraft:yellow_stained_glass_pane",
        "minecraft:lime_stained_glass_pane",
        "minecraft:pink_stained_glass_pane",
        "minecraft:gray_stained_glass_pane",
        "minecraft:light_gray_stained_glass_pane",
        "minecraft:cyan_stained_glass_pane",
        "minecraft:purple_stained_glass_pane",
        "minecraft:blue_stained_glass_pane",
        "minecraft:brown_stained_glass_pane",
        "minecraft:green_stained_glass_pane",
        "minecraft:red_stained_glass_pane",
        "minecraft:black_stained_glass_pane",
    ];

    
    overworld.runCommand(`tickingarea remove foMainPyramid`)

    
    if (progress.stage === "complete") {
        
        return;
    }
    
    system.runTimeout(() => {
        const pyramidBaseRadius = Math.floor(progress.size / 2);
        overworld.runCommand(`tickingarea add ${progress.x - pyramidBaseRadius - 3} -60 ${progress.z - pyramidBaseRadius - 3} ${progress.x + pyramidBaseRadius + 3} 80 ${progress.z + pyramidBaseRadius + 3} foMainPyramid`)
    }, 1);

    system.runTimeout(() => {

        
        if (progress.stage === "search") {
            findSafeLocation();
            system.runTimeout(mainPyramidLogic, 250 * fo.performanceModifier)
            return;
        }

        
        if (progress.stage === "pillar") {
            
            buildPillar();
            return;
        }

        
        if (progress.stage === "digging") {
            
            digPyramidStep();
            return;
        }

        
        if (progress.stage === "building" && !progress.paused) {
            
            buildPyramidStep();
            return;
        }

    }, 983) 

    

    
    function saveProgress(forceSave = false) {
        progress.blocksSinceLastSave++;

        if (forceSave || progress.blocksSinceLastSave >= progress.saveThreshold) {
            progress.saveThreshold = fo.performanceModifier === 1 ? 2 : fo.performanceModifier === 1.5 ? 3 : fo.performanceModifier === 2.5 ? 4 : 5
            progress.blocksSinceLastSave = 0;
            world.setDynamicProperty("mainPyramid", JSON.stringify(progress));
        }
    }

    
    function findSafeLocation() {
        const { x, z, size, height } = progress;

        const
            half = Math.floor(size / 2) + 1,
            bottomY = BASE_Y - 10,
            topY = BASE_Y + height + 5;

        let layer = 0;

        isSafeLocation(x, z, half, bottomY, topY, layer);

    }

    function isSafeLocation(px, pz, half, bottomY, topY, layer) {
        if (bottomY + layer > topY) return;

        
        if (layer === 0) {
            const entities = overworld.getEntities({
                location: { x: px, y: BASE_Y, z: pz },
                maxDistance: 100,
                families: ["minecraft:villager", "minecraft:armor_stand", "minecraft:boat"]
            });

            if (entities.length > 0) {
                
                progress.z += 100;
                saveProgress(true);
                return;
            }
        }

        
        const from = { x: px - half, y: bottomY + layer, z: pz - half };
        const to = { x: px + half, y: bottomY + layer, z: pz + half };
        const vol = new BlockVolume(from, to);

        if (overworld.containsBlock(vol, { includeTypes: playerMadeBlocks }, true)) {
            
            
            
            progress.z += 100;
            saveProgress(true);
            return;
        } else if (bottomY + layer === topY) {
            
            progress.stage = "pillar";
            saveProgress(true);
            return;
        }

        layer++
        system.runTimeout(() => {
            isSafeLocation(px, pz, half, bottomY, topY, layer);
        }, 4 * fo.performanceModifier)
    }

    
    function buildPillar() {
        const { x, z } = progress;
        const top = BASE_Y - 1;

        if (progress.currentY > top) {
            progress.stage = "digging";
            progress.currentY = BASE_Y; 
            progress.step = 0;
            saveProgress(true);
            digPyramidStep();
            return;
        }

        
        const totalBlocksPerLayer = 9; 
        const currentStep = progress.step;

        if (currentStep < totalBlocksPerLayer) {
            
            const dx = (currentStep % 3) - 1; 
            const dz = Math.floor(currentStep / 3) - 1; 

            if (Math.abs(dx) === 1 || Math.abs(dz) === 1) {
                overworld.setBlockType({ x: x + dx, y: progress.currentY, z: z + dz }, "minecraft:mossy_cobblestone");
            } else {
                overworld.setBlockType({ x: x + dx, y: progress.currentY, z: z + dz }, "minecraft:air"); 
            }

            progress.step++;
        }

        
        if (progress.step >= totalBlocksPerLayer) {
            progress.step = 0;
            progress.currentY++;
        }

        saveProgress();
        system.runTimeout(buildPillar, PLACE_INTERVAL);
    }

    
    function digPyramidStep() {
        const { x, z, size, height } = progress;

        
        const layer = height - 1 - (progress.currentY - BASE_Y);
        if (layer < 0) {
            progress.stage = "building";
            progress.currentY = BASE_Y;
            progress.step = 0;
            saveProgress(true);
            buildPyramidStep();
            
            return;
        }

        
        const nearPlayers = overworld.getPlayers({
            location: { x, y: BASE_Y, z },
            maxDistance: PROXIMITY_RADIUS
        });
        if (nearPlayers.length > 0) {
            system.runTimeout(digPyramidStep, 200);
            return;
        }

        
        if (fo.performanceModifier >= 2.5 && layer < 22) {
            const layerSize = size - layer * 2;
            const half = Math.floor(layerSize / 2);
            const y = BASE_Y + layer;

            const from = { x: x - half, y: y, z: z - half };
            const to = { x: x + half, y: y, z: z + half };

            const volume = new BlockVolume(from, to);
            const airBlock = BlockPermutation.resolve("minecraft:air");

            overworld.fillBlocks(volume, airBlock);

            progress.currentY++;
            saveProgress(true);
            system.runTimeout(digPyramidStep, PLACE_INTERVAL * 10);
            return;
        }

        const layerSize = size - layer * 2;
        const half = Math.floor(layerSize / 2);
        const y = BASE_Y + layer;

        
        const totalBlocks = layerSize * layerSize;

        if (progress.step < totalBlocks) {
            const i = progress.step;

            
            const dx = -half + (i % layerSize);
            const dz = -half + Math.floor(i / layerSize);

            const stepBlock = overworld.getBlock({ x: x + dx, y, z: z + dz });

            if (!stepBlock.isAir) {
                
                stepBlock.setType("minecraft:air")

                system.runTimeout(digPyramidStep, PLACE_INTERVAL);
            } else {
                system.runTimeout(digPyramidStep, 1);
            }

            progress.step++;
            saveProgress();

            return;
        }

        
        progress.currentY++;
        progress.step = 0;
        saveProgress();
        system.runTimeout(digPyramidStep, PLACE_INTERVAL);
    }


    
    function buildPyramidStep() {
        if (progress.paused) return;

        const { x, z, size, height } = progress;

        const layer = progress.currentY - BASE_Y;
        if (layer >= height) {
            progress.stage = "complete";
            saveProgress(true);
            world.setDefaultSpawnLocation({ x: x, y: BASE_Y + height + 1, z: z })
            overworld.runCommand(`tickingarea remove foMainPyramid`)
            
            return;
        }

        
        const nearPlayers = overworld.getPlayers({
            location: { x, y: BASE_Y, z },
            maxDistance: PROXIMITY_RADIUS
        });
        if (nearPlayers.length > 0) {
            system.runTimeout(buildPyramidStep, 200);
            return;
        }

        const layerSize = size - layer * 2;
        const half = Math.floor(layerSize / 2);
        const y = BASE_Y + layer;

        
        const perimeterCount = layerSize * 4 - 4;
        if (progress.step <= perimeterCount) {
            const i = progress.step;
            let dx, dz;

            if (i < layerSize) { dx = -half + i; dz = -half; }
            else if (i < layerSize * 2 - 1) { dx = half; dz = -half + (i - layerSize + 1); }
            else if (i < layerSize * 3 - 2) { dx = half - (i - (layerSize * 2 - 1)); dz = half; }
            else { dx = -half; dz = half - (i - (layerSize * 3 - 2)); }

            overworld.setBlockType({ x: x + dx, y, z: z + dz }, "minecraft:mossy_cobblestone");

            progress.step++;
            if (layer === 27 && (progress.step - 1) === Math.floor(perimeterCount * 0.35)) {
                progress.pausedx = x + dx;
                progress.pausedy = y + 1;
                progress.pausedz = z + dz;
                progress.paused = true;
                

                
                for (let x = -1; x <= 1; x++) {
                    for (let y = 0; y <= 2; y++) {
                        for (let z = -1; z <= 1; z++) {
                            const block = overworld.getBlock({
                                x: Math.floor(progress.pausedx) + x,
                                y: Math.floor(progress.pausedy) + y,
                                z: Math.floor(progress.pausedz) + z,
                            });
                            if (block) block.setType("minecraft:air");
                        }
                    }
                }
                saveProgress(true);
                return;
            };
            saveProgress();

            system.runTimeout(buildPyramidStep, PLACE_INTERVAL * 3);

            return;
        }

        const from = { x: x - half + 1, y: y, z: z - half + 1 };
        const to = { x: x + half - 1, y: y, z: z + half - 1 };
        const volume = new BlockVolume(from, to);

        
        if (layer === 0) { 
            const mossy = BlockPermutation.resolve("minecraft:mossy_cobblestone");
            overworld.fillBlocks(volume, mossy);

            
            system.runTimeout(() => {
                overworld.setBlockType({ x: x, y, z: z }, "minecraft:water");
            }, 1);

        } else {
            const water = BlockPermutation.resolve("minecraft:water");
            overworld.fillBlocks(volume, water);
        }

        
        progress.currentY++;
        progress.step = 0;
        saveProgress(true);
        system.runTimeout(buildPyramidStep, PLACE_INTERVAL * 10);
    }
};
