import { DisplaySlotId, system, world } from "@minecraft/server";

const PRINTWARNING = true
const biomes = [
    "minecraft:bamboo_jungle",
    "minecraft:bamboo_jungle_hills",
    "minecraft:basalt_deltas",
    "minecraft:beach",
    "minecraft:birch_forest",
    "minecraft:birch_forest_hills",
    "minecraft:birch_forest_hills_mutated",
    "minecraft:birch_forest_mutated",
    "minecraft:cherry_grove",
    "minecraft:cold_beach",
    "minecraft:cold_ocean",
    "minecraft:cold_taiga",
    "minecraft:cold_taiga_hills",
    "minecraft:cold_taiga_mutated",
    "minecraft:crimson_forest",
    "minecraft:deep_cold_ocean",
    "minecraft:deep_dark",
    "minecraft:deep_frozen_ocean",
    "minecraft:deep_lukewarm_ocean",
    "minecraft:deep_ocean",
    "minecraft:deep_warm_ocean",
    "minecraft:desert",
    "minecraft:desert_hills",
    "minecraft:desert_mutated",
    "minecraft:dripstone_caves",
    "minecraft:extreme_hills",
    "minecraft:extreme_hills_edge",
    "minecraft:extreme_hills_mutated",
    "minecraft:extreme_hills_plus_trees",
    "minecraft:extreme_hills_plus_trees_mutated",
    "minecraft:flower_forest",
    "minecraft:forest",
    "minecraft:forest_hills",
    "minecraft:frozen_ocean",
    "minecraft:frozen_peaks",
    "minecraft:frozen_river",
    "minecraft:grove",
    "minecraft:hell",
    "minecraft:ice_mountains",
    "minecraft:ice_plains",
    "minecraft:ice_plains_spikes",
    "minecraft:jagged_peaks",
    "minecraft:jungle",
    "minecraft:jungle_edge",
    "minecraft:jungle_edge_mutated",
    "minecraft:jungle_hills",
    "minecraft:jungle_mutated",
    "minecraft:legacy_frozen_ocean",
    "minecraft:lukewarm_ocean",
    "minecraft:lush_caves",
    "minecraft:mangrove_swamp",
    "minecraft:meadow",
    "minecraft:mega_taiga",
    "minecraft:mega_taiga_hills",
    "minecraft:mesa",
    "minecraft:mesa_bryce",
    "minecraft:mesa_plateau",
    "minecraft:mesa_plateau_mutated",
    "minecraft:mesa_plateau_stone",
    "minecraft:mesa_plateau_stone_mutated",
    "minecraft:mushroom_island",
    "minecraft:mushroom_island_shore",
    "minecraft:ocean",
    "minecraft:plains",
    "minecraft:redwood_taiga_hills_mutated",
    "minecraft:redwood_taiga_mutated",
    "minecraft:river",
    "minecraft:roofed_forest",
    "minecraft:roofed_forest_mutated",
    "minecraft:savanna",
    "minecraft:savanna_mutated",
    "minecraft:savanna_plateau",
    "minecraft:savanna_plateau_mutated",
    "minecraft:snowy_slopes",
    "minecraft:soulsand_valley",
    "minecraft:stone_beach",
    "minecraft:stony_peaks",
    "minecraft:sunflower_plains",
    "minecraft:swampland",
    "minecraft:swampland_mutated",
    "minecraft:taiga",
    "minecraft:taiga_hills",
    "minecraft:taiga_mutated",
    "minecraft:the_end",
    "minecraft:warm_ocean",
    "minecraft:warped_forest"
]

for (const biome of biomes) {
    const spawnRateScoreboard = world.scoreboard.getObjective(biome)
    if (!spawnRateScoreboard) world.scoreboard.addObjective(biome, biome)
}
world.afterEvents.entitySpawn.subscribe(ev => {
    const entity = ev.entity
    if (!entity.isValid()) return PRINTWARNING ? console.warn(entity.typeId, "cancelled spawning") : ""
    if (!entity.getComponent("minecraft:type_family")?.hasTypeFamily("mob")) return
    let smallestDistance = 9999999999;
    let chosenBiome;
    const point2 = entity.location
    for (const biome of biomes) {
        const point1 = entity.dimension.findClosestBiome(entity.location, biome, {boundingSize: { x: 64, y: 64, z: 64 }});
        if (!point1) continue
        
        const distance1 = Math.pow(point2.x - point1.x, 2) + 
        Math.pow(point2.y - point1.y, 2) + 
        Math.pow(point2.z - point1.z, 2);

        if (distance1 >= smallestDistance) continue
        chosenBiome = biome
        smallestDistance = distance1
    }   
    let scoreboard = world.scoreboard.getObjective(chosenBiome)
    const newLocal = entity.typeId.replace("piki_beyondsurvival:", "p:").replace("minecraft:", "m:");
    scoreboard.addScore(newLocal, 1)
    if (PRINTWARNING) console.warn(
        newLocal.toString().padEnd(), 
        Math.trunc(entity.location.x), 
        Math.trunc(entity.location.y), 
        Math.trunc(entity.location.z), 
        world.getTimeOfDay(), 
        chosenBiome
    )
    
})
system.runInterval(() => {
    for (const player of world.getAllPlayers()) {
        
        let smallestDistance = 9999999999;
        let chosenBiome;
        const point2 = player.location
        for (const biome of biomes) {
            const point1 = player.dimension.findClosestBiome(player.location, biome, { boundingSize: { x: 64, y: 64, z: 64 }});
            if (!point1) continue

            const distance1 = Math.pow(point2.x - point1.x, 2) + 
            Math.pow(point2.y - point1.y, 2) + 
            Math.pow(point2.z - point1.z, 2);
    
            if (distance1 >= smallestDistance) continue
            chosenBiome = biome
            smallestDistance = distance1
            
        }
        let scoreboard = world.scoreboard.getObjective(chosenBiome)
        scoreboard.addScore("secondsVisited", 1)
        world.scoreboard.setObjectiveAtDisplaySlot(DisplaySlotId.Sidebar, {objective: scoreboard})
    }
}, 20)

world.afterEvents.itemUse.subscribe(ev => {
    const {itemStack, source} = ev
    const itemStackId = itemStack.typeId

    console.warn("===============================")
    if (itemStackId == "minecraft:blaze_rod") {
        for (const biome of biomes) {
            let scoreboard = world.scoreboard.getObjective(biome)
            let text = "Biome: " + biome + "\n"
            for (const p of scoreboard.getScores()) {
                text += p.participant.displayName, ":", p.score + "\n"
            }
            console.warn(text)
        }
    } 

})