import { world, system, BlockVolume, ItemStack, FeedItem } from "@minecraft/server";
import { checkRankUpLevel, setPlayerExp, levelMap, getPlayerExp, getPlayerLevel, getExpFromLevel } from "./combatmastery";

const MARKER_CONFIGS = {
    "msft:small_castle_marker": { searchRadius: 30, spawnerCheckRadius: 40 },
    "msft:small_house_marker": { searchRadius: 30, spawnerCheckRadius: 30 },
    "msft:small_tower_marker": { searchRadius: 30, spawnerCheckRadius: 20 },
    "msft:warden_marker": { searchRadius: 30, spawnerCheckRadius: 40 },
    "msft:spawn_marker": { searchRadius: 10, spawnerCheckRadius: 20 },
};
const MOB_SPAWNER_ID = "minecraft:mob_spawner";
const CHECK_INTERVAL = 20;
let TEMP_MARKER = null;

const totalSpawnersMap = new Map();
const remainingSpawnersMap = new Map();
const playersInStructure = new Map();

function findStructuresAndCountSpawners() {
    const dimension = world.getDimension("overworld");
    const players = world.getPlayers();

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

    players.forEach(player => {
        const playerLocation = player.location;

        const nearbyEntities = dimension.getEntities({
            location: playerLocation,
            maxDistance: 100,  // Cerca qualsiasi marker
            excludeTypes: ["minecraft:player"]
        });

        let foundMarker = null;

        for (const entity of nearbyEntities) {
            if (MARKER_CONFIGS[entity.typeId]) {
                foundMarker = entity;
                break;
            }
        }

        // **Se non troviamo marker, controlliamo se il player deve uscire**
        if (!foundMarker) {
            if (playersInStructure.has(player.id)) {
                hidePlayerHUD(player);
                playersInStructure.delete(player.id);
            }
            return;
        }

        TEMP_MARKER = foundMarker.typeId;
        const markerConfig = MARKER_CONFIGS[TEMP_MARKER];
        const searchRadius = markerConfig.searchRadius;
        const spawnerCheckRadius = markerConfig.spawnerCheckRadius;

        const distance = Math.sqrt(
            Math.pow(foundMarker.location.x - Math.floor(playerLocation.x), 2) +
            Math.pow(foundMarker.location.y - Math.floor(playerLocation.y), 2) +
            Math.pow(foundMarker.location.z - Math.floor(playerLocation.z), 2)
        );

        const key = `${Math.floor(foundMarker.location.x)},${Math.floor(foundMarker.location.y)},${Math.floor(foundMarker.location.z)}`;

        // **Fase 2: Se il player esce, nasconde l’HUD ma NON tocca gli spawner**
        if (distance > searchRadius) {
            if (playersInStructure.has(player.id)) {
                hidePlayerHUD(player);
                playersInStructure.delete(player.id);
            }
            return;
        }

        // **Fase 3: Se il player è dentro, aggiorna gli spawner solo alla prima entrata**
        if (!playersInStructure.has(player.id)) {
            const spawnerCount = countSpawnersInArea(dimension, foundMarker.location, spawnerCheckRadius);

            if (spawnerCount <= 0) {
                TEMP_MARKER = null;
                return;
            }

            if (TEMP_MARKER == "msft:spawn_marker") {
                player.removeEffect("minecraft:mining_fatigue");
            } else {
                player.runCommandAsync(`titleraw @s times 15 30 15`);
                player.runCommandAsync(`title @s title title_dungeon_begins`);
                player.runCommandAsync(`titleraw @s times 0 0 0`);
                player.playSound(`msft:ambient_dungeon:join_dungeon_normal`);
            }
            //console.log(spawnerCount);
            remainingSpawnersMap.set(key, spawnerCount);
            if (!totalSpawnersMap.has(key) || totalSpawnersMap.get(key) < spawnerCount) {
                totalSpawnersMap.set(key, spawnerCount);
            }

            playersInStructure.set(player.id, key);

            system.runTimeout(() => {
                sendSpawnerCountMessage(player, key);
            }, 60);
        }
    });
}


function hidePlayerHUD(player) {
    player.runCommandAsync(`titleraw @s times 0 0 0`);
    player.runCommandAsync(`titleraw @s title {"rawtext":[{"text":"hud:dungeon:hide_ui"}]}`);
    TEMP_MARKER = null;
}


function countSpawnersInArea(dimension, center, radius) {
    const bounds = {
        minX: Math.floor(center.x - radius),
        maxX: Math.floor(center.x + radius),
        minY: Math.floor(center.y - radius),
        maxY: Math.floor(center.y + radius),
        minZ: Math.floor(center.z - radius),
        maxZ: Math.floor(center.z + radius),
    };

    const volume = new BlockVolume(
        { x: bounds.minX, y: bounds.minY, z: bounds.minZ },
        { x: bounds.maxX, y: bounds.maxY, z: bounds.maxZ }
    );

    const blocks = dimension.getBlocks(volume, { includeTypes: [MOB_SPAWNER_ID] }, true);
    const blockIterator = blocks.getBlockLocationIterator();

    let spawnerCount = 0;

    for (const block of blockIterator) {
        //console.log("aaaa: " + JSON.stringify(block));
        spawnerCount++;
    }

    return spawnerCount;
}

world.beforeEvents.playerBreakBlock.subscribe(event => {

    
    const { block, player } = event;

    const exp = getPlayerExp(player);
    const level = getPlayerLevel(player);


    if (block.typeId === MOB_SPAWNER_ID && playersInStructure.has(player.id)) {
        const locationKey = playersInStructure.get(player.id);
        const remaining = remainingSpawnersMap.get(locationKey) || 0;

        if (remaining > 0) {
            remainingSpawnersMap.set(locationKey, remaining - 1);

            player.sendMessage("§eYou gained +25 XP!");

            if (!checkRankUpLevel(player, exp, level)) {
                const newExp = exp + 25;
                setPlayerExp(player, newExp);
                levelMap.set(player.id, {level: level, exp: newExp, totalExp: getExpFromLevel(level)});
            }
            system.run(() => {
                player.playSound("msft:ambient:destroy_mob_spawner");
            })

            const keys = playersInStructure.keys();
            for (const key of keys) {
                if (key && locationKey === playersInStructure.get(key)) {
                    sendSpawnerCountMessage(world.getEntity(key), locationKey);
                }
            }
        }
    }
});

function sendSpawnerCountMessage(player, locationKey) {

    const remaining = remainingSpawnersMap.get(locationKey) || 0;
    const total = totalSpawnersMap.get(locationKey) || 0;

    if (remaining === 0) {
        player.runCommandAsync(`titleraw @s times 15 30 15`);
        player.runCommandAsync(`title @s title title_dungeon_cleared`);
        player.runCommandAsync(`titleraw @s times 0 0 0`);
        system.run(() => {
            player.playSound("msft:ambient_dungeon:complete_dungeon_normal");
        });

        const firstPlayer = player.dimension.getEntities({
            location: player.location,
            maxDistance: 20
        }).filter(player => player.typeId.includes("minecraft:player"))[0];


        const exp = getPlayerExp(player);
        const level = getPlayerLevel(player);

        switch(TEMP_MARKER) {
            case "msft:spawn_marker":
            case "msft:small_tower_marker":
            case "msft:small_house_marker":
            firstPlayer.sendMessage("§aYou received an Iron Key in your inventory! Find and open the chest!");

            const inventory = firstPlayer.getComponent("minecraft:inventory").container;
            const key = new ItemStack("msft:iron_key", 1);
            system.run(() => inventory.addItem(key));

            firstPlayer.sendMessage("§eYou gained +280 XP!");
            if (!checkRankUpLevel(player, exp, level)) {
                const newExp = exp + 280;
                setPlayerExp(player, newExp);
                levelMap.set(player.id, {level: level, exp: newExp, totalExp: getExpFromLevel(level)});
            }

            break;
            case "msft:small_castle_marker":
            firstPlayer.sendMessage("§aYou received an Golden Key in your inventory! Find and open the chest!");

            const inventoryG = firstPlayer.getComponent("minecraft:inventory").container;
            const keyG = new ItemStack("msft:golden_key", 1);
            system.run(() => inventoryG.addItem(keyG));

            firstPlayer.sendMessage("§eYou gained +700 XP!");
            if (!checkRankUpLevel(player, exp, level)) {
                const newExp = exp + 700;
                setPlayerExp(player, newExp);
                levelMap.set(player.id, {level: level, exp: newExp, totalExp: getExpFromLevel(level)});
            }
            break;
            case "msft:warden_marker":
            firstPlayer.sendMessage("§aYou received an Diamond Key in your inventory! Find and open the chest!");

            const inventoryD = firstPlayer.getComponent("minecraft:inventory").container;
            const keyD = new ItemStack("msft:diamond_key", 1);
            system.run(() => inventoryD.addItem(keyD));

            firstPlayer.sendMessage("§eYou gained +1400 XP!");
            if (!checkRankUpLevel(player, exp, level)) {
                const newExp = exp + 1400;
                setPlayerExp(player, newExp);
                levelMap.set(player.id, {level: level, exp: newExp, totalExp: getExpFromLevel(level)});
            }
            break;
        }


        if (TEMP_MARKER == "msft:spawn_marker") {

            const doorEntity = player.dimension.getEntities({
                location: player.location,
                maxDistance: 100
            }).filter(entity => entity.typeId.includes("door_tutorial"))[0];

            //console.log(doorEntity);
            system.run(() => {
                doorEntity.setProperty("msft:open_tutorial", true);
            })
            removeBarriers(doorEntity.dimension, doorEntity.location, 5);
        }

        TEMP_MARKER = null;
    } else {
        //console.log(TEMP_MARKER);
        if (TEMP_MARKER == "msft:spawn_marker") {
            system.run(() => player.removeEffect("minecraft:mining_fatigue"));
        }
        let message = `hud:dungeon:§e§lᴅᴇsᴛʀᴏʏ ᴀʟʟ ᴛʜᴇ ᴍᴏʙ sᴘᴀᴡɴᴇʀs: §c§l${remaining}/${total}`;
        player.runCommandAsync(`titleraw @s times 0 0 0`);
        player.runCommandAsync(`titleraw @s title {"rawtext":[{"text":"${message}"}]}`);
    }
}
function removeBarriers(dimension, centerPos, radius = 5) {
    for (let x = -radius; x <= radius; x++) {
        for (let y = -radius; y <= radius; y++) {
            for (let z = -radius; z <= radius; z++) {
                const blockPos = {
                    x: Math.floor(centerPos.x + x),
                    y: Math.floor(centerPos.y + y),
                    z: Math.floor(centerPos.z + z)
                };

                const block = dimension.getBlock(blockPos);

                if (block && block.typeId === "minecraft:barrier") {
                    system.run(() => {
                        block.setType("minecraft:air");
                    })
                }
            }
        }
    }
}

world.afterEvents.playerSpawn.subscribe(event => {
    if (event.initialSpawn) {
        const player = event.player;
        player.runCommandAsync(`titleraw @s times 0 0 0`);
        player.runCommandAsync(`titleraw @s title {"rawtext":[{"text":"hud:dungeon:hide_ui"}]}`);
    }
})

system.runInterval(() => {
    findStructuresAndCountSpawners();
}, CHECK_INTERVAL);