import { system, world } from "@minecraft/server";
import noise from "./noise";
import { WorldDB } from "./eternal/modules/worldDB";

// Store the last known chunk position for each player
const db = new WorldDB("biomeGenerator");

// Seed the noise generator for consistent results
noise.seedWithString("Eternal");

// Function to generate biomes around the player based on noise map
function generateBiomeAroundPlayer(player, chunkRadius) {
  const playerChunkX = Math.floor(player.location.x / 16);
  const playerChunkZ = Math.floor(player.location.z / 16);

  // Retrieve or initialize the generated chunks for this player
  const generatedChunks = db.get("generatedChunk") ?? new Set();

  for (let chunkX = playerChunkX - chunkRadius; chunkX <= playerChunkX + chunkRadius; chunkX++) {
    for (let chunkZ = playerChunkZ - chunkRadius; chunkZ <= playerChunkZ + chunkRadius; chunkZ++) {
      const chunkLocation = `${chunkX},${chunkZ}`; // Use string for storing chunk location
      if (!generatedChunks.has(chunkLocation)) {
        generateBiomeUsingNoise(chunkX * 16, chunkZ * 16);
        generatedChunks.add(chunkLocation);
      }
    }
  }

  // Update the generated chunks for the player in the database
  db.set("generatedChunk", generatedChunks);
}

// Generate biome terrain using noise map for height and biome type
function generateBiomeUsingNoise(xStart, zStart) {
  const chunkSize = 16;

  for (let x = xStart; x < xStart + chunkSize; x++) {
    for (let z = zStart; z < zStart + chunkSize; z++) {
      const noiseValue = noise.perlin2(x / 100, z / 100); // Generate noise value (scaled for smoothness)
      const height = generateHeightFromNoise(noiseValue); // Generate height from noise
      createBiomeColumn(x, z, height, noiseValue); // Create column based on noise
    }
  }
}

// Convert noise value to terrain height
function generateHeightFromNoise(noiseValue) {
  const baseHeight = 5;
  const amplitude = 10;
  return Math.floor(baseHeight + amplitude * noiseValue); // Adjust height based on noise
}

// Create a terrain column using noise to determine the block types
function createBiomeColumn(x, z, height, noiseValue) {
  const dimension = world.getDimension("overworld");

  for (let y = 0; y <= height; y++) {
    const blockLocation = { x, y, z };
    const block = dimension.getBlock(blockLocation);

    if (block) {
      // Use noise value to decide block types for different biomes
      if (noiseValue > 0.3) {
        if (y === height) {
          block.setType("minecraft:short_grass");
        } else if (y > height - 4) {
          block.setType("minecraft:dirt");
        } else {
          block.setType("minecraft:stone");
        }
      } else {
        if (y === height) {
          block.setType("minecraft:sand");
        } else if (y > height - 4) {
          block.setType("minecraft:sandstone");
        } else {
          block.setType("minecraft:stone");
        }
      }
    }
  }
}

// Function to check and generate biomes for all players
function updateBiomesForPlayer(player) {
  const chunkRadius = 4; // Number of chunks around the player
  generateBiomeAroundPlayer(player, chunkRadius);
}

// Main execution: Continuously check for player movement
system.runInterval(() => {
  world.getAllPlayers().forEach((player) => {
    // Check if player has moved to a different chunk
    const currentChunkX = Math.floor(player.location.x / 16);
    const currentChunkZ = Math.floor(player.location.z / 16);

    const lastChunk = db.get(player.id);
    if (!lastChunk || !lastChunk.has(`${currentChunkX},${currentChunkZ}`)) {
      updateBiomesForPlayer(player);
    }
  });
}, 20);
