package ca.recrown.islandsurvivalcraft.world.generation;

import java.security.InvalidAlgorithmParameterException;
import java.util.Random;

import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData;

import ca.recrown.islandsurvivalcraft.world.BiomeSelector;
import ca.recrown.islandsurvivalcraft.world.IslandWorldMapper;
import ca.recrown.islandsurvivalcraft.world.shaders.WorldHeightShader;

/**
 * A world generator.
 */
public class IslandWorldGenerator {
    private final int maxHeight;
    private final BedrockGenerator bedrockGenerator;
    private final BiomeSelector biomeSelector;
    private final IslandBiomeGenerator biomeGenerator;
    private final WorldHeightShader heightShader;
    public final World world;
    public final IslandWorldMapper islandMapGenerator;
    public final Random random;

    public IslandWorldGenerator(World world, IslandBiomeGenerator islandBiomeGenerator, Random random) {
        this.world = world;
        this.maxHeight = world.getMaxHeight();
        this.random = random;
        this.biomeSelector = new BiomeSelector(random);
        this.islandMapGenerator = new IslandWorldMapper(random);
        this.biomeGenerator = islandBiomeGenerator;

        int bedrockMaxHeight = 5;
        int bedrockMinHeight = 1;
        this.bedrockGenerator = new BedrockGenerator(random, bedrockMaxHeight, bedrockMinHeight);
        this.heightShader = new WorldHeightShader(world.getSeed(), islandMapGenerator, world.getSeaLevel(), maxHeight,
                bedrockMaxHeight + 2);
        biomeSelector.initialize();
        islandBiomeGenerator.initialize(world, islandMapGenerator, biomeSelector);
    }

    public void GenerateChunk(int chunkX, int chunkZ, int localX, int localZ, ChunkData chunk, BiomeGrid biomeGrid) {
        int worldX = 16 * chunkX + localX;
        int worldZ = 16 * chunkZ + localZ;
        // gets the bedrock.
        int bedrockHeight = bedrockGenerator.getBedrockHeight(worldX, worldZ);

        //Sets the biome.
        Biome currentBiome = biomeGenerator.GenerateBiome(chunkX, chunkZ, localX, localZ);
        if (currentBiome == null) throw new IllegalStateException("Biome generated was null!");
        for (int y = 0; y < maxHeight; y++) {
            biomeGrid.setBiome(localX, y, localZ, currentBiome);
        }

        //get height shader.
        int height = 0;
        try {
            height = heightShader.getAltitude(worldX, worldZ, currentBiome);
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
            height = maxHeight;
        }
        if (height == 0) throw new IllegalStateException("Height generated was null!");

        //set general shape
        chunk.setRegion(localX, 0, localZ, localX + 1, height, localZ + 1, Material.STONE);

        //set bedrock last
        chunk.setRegion(localX, 0, localZ, localX + 1, bedrockHeight, localZ + 1, Material.BEDROCK);
    }
}