package telinc.telicraft.world.gen.feature;

import java.util.Random;

import net.minecraft.block.Block;
import net.minecraft.world.World;
import net.minecraft.world.WorldType;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.gen.feature.WorldGenerator;

import net.minecraftforge.common.BiomeDictionary;
import net.minecraftforge.common.BiomeDictionary.Type;

import telinc.telicraft.block.TelicraftBlocks;

/**
 * Handles generating Impact Craters/Meteor Craters.
 * 
 * @author Mithion's .schematic to .java converter version 1.7
 */
public class WorldGenImpactCrater extends WorldGenerator {
    @Override
    public boolean generate(World world, Random rand, int x, int y, int z) {
        BiomeGenBase biome = world.getWorldChunkManager().getBiomeGenAt(x, z);

        // Check that each corner is one of the valid spawn blocks
        if(!this.locationIsValidSpawn(world, x, y, z) || !this.locationIsValidSpawn(world, x + 3, y, z) || !this.locationIsValidSpawn(world, x + 3, y, z + 3) || !this.locationIsValidSpawn(world, x, y, z + 3)){
            return false;
        }

        int failureProbability = rand.nextInt(100);

        if(BiomeDictionary.isBiomeOfType(biome, Type.DESERT) || BiomeDictionary.isBiomeOfType(biome, Type.BEACH) || world.getWorldInfo().getTerrainType() == WorldType.FLAT){
            if(failureProbability < 6){
                this.genBlocks(world, x, y, z);
                return true;
            }
        }else{
            if(failureProbability < 38){
                this.genBlocks(world, x, y, z);
                return true;
            }
        }

        return false;
    }

    private void genBlocks(World world, int x, int y, int z) {
        world.setBlock(x + 0, y + 0, z + 1, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 0, y + 0, z + 2, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 0, y + 1, z + 1, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 0, y + 1, z + 2, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 0, y + 2, z + 1, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 0, y + 2, z + 2, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 1, y + 0, z + 0, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 1, y + 0, z + 1, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 1, y + 0, z + 2, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 1, y + 0, z + 3, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 1, y + 1, z + 0, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 1, y + 1, z + 1, 0, 0, 2);
        world.setBlock(x + 1, y + 1, z + 2, 0, 0, 2);
        world.setBlock(x + 1, y + 1, z + 3, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 1, y + 2, z + 0, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 1, y + 2, z + 1, 0, 0, 2);
        world.setBlock(x + 1, y + 2, z + 2, 0, 0, 2);
        world.setBlock(x + 1, y + 2, z + 3, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 2, y + 0, z + 0, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 2, y + 0, z + 1, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 2, y + 0, z + 2, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 2, y + 0, z + 3, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 2, y + 1, z + 0, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 2, y + 1, z + 1, 0, 0, 2);
        world.setBlock(x + 2, y + 1, z + 2, 0, 0, 2);
        world.setBlock(x + 2, y + 1, z + 3, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 2, y + 2, z + 0, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 2, y + 2, z + 1, 0, 0, 2);
        world.setBlock(x + 2, y + 2, z + 2, 0, 0, 2);
        world.setBlock(x + 2, y + 2, z + 3, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 3, y + 0, z + 1, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 3, y + 0, z + 2, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 3, y + 1, z + 1, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 3, y + 1, z + 2, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 3, y + 2, z + 1, TelicraftBlocks.meteorBlock.blockID, 0, 2);
        world.setBlock(x + 3, y + 2, z + 2, TelicraftBlocks.meteorBlock.blockID, 0, 2);
    }

    private boolean locationIsValidSpawn(World world, int x, int y, int z) {
        int distanceToAir = 0;
        int checkID = world.getBlockId(x, y, z);

        while(checkID != 0){
            distanceToAir++;
            checkID = world.getBlockId(x, y + distanceToAir, z);
        }

        if(distanceToAir > 12){
            return false;
        }

        y += distanceToAir - 1;

        int blockID = world.getBlockId(x, y, z);
        int blockIDAbove = world.getBlockId(x, y + 1, z);
        int blockIDBelow = world.getBlockId(x, y - 1, z);

        for(int block : this.getValidSpawnBlocks()){
            if(blockIDAbove != 0){
                return false;
            }

            if(blockID == block){
                return true;
            }else if(blockID == Block.snow.blockID && blockIDBelow == block){
                return true;
            }
        }

        return false;
    }

    private int[] getValidSpawnBlocks() {
        return new int[]{Block.grass.blockID, Block.sand.blockID};
    }
}