package com.khorn.terraincontrol.forge.generator.structure;

import com.khorn.terraincontrol.LocalBiome;
import com.khorn.terraincontrol.LocalWorld;
import com.khorn.terraincontrol.TerrainControl;
import com.khorn.terraincontrol.configuration.BiomeConfig;
import com.khorn.terraincontrol.configuration.BiomeConfig.VillageType;
import com.khorn.terraincontrol.forge.util.WorldHelper;
import com.khorn.terraincontrol.logging.LogMarker;
import net.minecraft.world.World;
import net.minecraft.world.gen.structure.StructureComponent;
import net.minecraft.world.gen.structure.StructureStart;
import net.minecraft.world.gen.structure.StructureVillagePieces;
import net.minecraft.world.gen.structure.StructureVillagePieces.PieceWeight;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Random;

public class TXVillageStart extends StructureStart
{
    // well ... thats what it does
    private boolean hasMoreThanTwoComponents = false;

    public TXVillageStart(World world, Random random, int chunkX, int chunkZ, int size)
    {
        List<PieceWeight> villagePieces = StructureVillagePieces.getStructureVillageWeightedPieceList(random, size);

        int startX = (chunkX << 4) + 2;
        int startZ = (chunkZ << 4) + 2;
        StructureVillagePieces.Start startPiece = new StructureVillagePieces.Start(world.getBiomeProvider(), 0, random, startX, startZ, villagePieces, size);

        // Apply the villageType setting
        LocalWorld worldTC = WorldHelper.toLocalWorld(world);
        LocalBiome currentBiome = worldTC.getBiome(startX, startZ);
        BiomeConfig config = currentBiome.getBiomeConfig();
        if (config != null)
        {
            // Ignore removed custom biomes
            changeToSandstoneVillage(startPiece, config.villageType == VillageType.sandstone);
        }

        this.components.add(startPiece);
        startPiece.buildComponent(startPiece, this.components, random);
        List<StructureComponent> var8 = startPiece.pendingRoads;
        List<StructureComponent> var9 = startPiece.pendingHouses;
        int var10;

        while (!var8.isEmpty() || !var9.isEmpty())
        {
            StructureComponent var11;

            if (var8.isEmpty())
            {
                var10 = random.nextInt(var9.size());
                var11 = var9.remove(var10);
                var11.buildComponent(startPiece, this.components, random);
            } else
            {
                var10 = random.nextInt(var8.size());
                var11 = var8.remove(var10);
                var11.buildComponent(startPiece, this.components, random);
            }
        }

        this.updateBoundingBox();
        var10 = 0;

        for (Object component : this.components)
        {
            StructureComponent var12 = (StructureComponent) component;

            if (!(var12 instanceof StructureVillagePieces.Road))
            {
                ++var10;
            }
        }

        this.hasMoreThanTwoComponents = var10 > 2;
    }

    /**
     * Just sets the first boolean it can find in the
     * WorldGenVillageStartPiece.class to sandstoneVillage.
     *
     * @param subject          The village.
     * @param sandstoneVillage Whether the village should be a sandstone
     *                         village.
     */
    private void changeToSandstoneVillage(StructureVillagePieces.Start subject, boolean sandstoneVillage)
    {
        for (Field field : StructureVillagePieces.Start.class.getFields())
        {
            if (field.getType().toString().equals("boolean"))
            {
                try
                {
                    field.setAccessible(true);
                    field.setBoolean(subject, sandstoneVillage);
                    break;
                } catch (Exception e)
                {
                    TerrainControl.log(LogMarker.FATAL, "Cannot make village a sandstone village!");
                    TerrainControl.printStackTrace(LogMarker.FATAL, e);
                }
            }
        }
    }

    /**
     * currently only defined for Villages, returns true if Village has more than 2 non-road components
     */
    @Override
    public boolean isSizeableStructure()
    {
        return this.hasMoreThanTwoComponents;
    }

    public TXVillageStart()
    {
        // Required by Minecraft's structure loading code
    }
}

@@ -1728,34 +1728,27 @@
   change
-ToSandstone
 Village
+Type
 (startPi
@@ -1786,25 +1786,172 @@
 ageType.
-sandstone
+wood ? 0 : config.villageType == VillageType.sandstone ? 1 : config.villageType == VillageType.savanna ? 2 : config.villageType == VillageType.taiga ? 3 : 0
 );%0A     
@@ -3461,26 +3461,19 @@
 ange
-ToSandstone
 Village
+Type
 (Str
@@ -3511,32 +3511,23 @@
 ct, 
-boolean sandstoneV
+int v
 illage
+Type
 )%0A  
@@ -3557,16 +3557,50 @@
 field : 
+net.minecraft.world.gen.structure.
 Structur
@@ -3614,21 +3614,23 @@
 ePieces.
-Start
+Village
 .class.g
@@ -3631,16 +3631,24 @@
 lass.get
+Declared
 Fields()
@@ -3675,57 +3675,285 @@
     
-if (field.getType().toString().equals(%22boolean%22))
+String fieldName = field.getName();%0A            if (fieldName.equals(%22structureType%22) %7C%7C fieldName.equals(%22field_189928_h%22)) // field_189928_h may have to be updated for newer versions of mc/forge (%3E 1.10.2), see http://export.mcpbot.bspk.rs/ for obfuscated method/field names.
 %0A   
@@ -4081,15 +4081,11 @@
 .set
-Boolean
+Int
 (sub
@@ -4090,32 +4090,27 @@
 ubject, 
-sandstoneV
+v
 illage
+Type
 );%0A     
@@ -4255,40 +4255,29 @@
 not 
-make village a sandstone
+set specified
  village
 !%22);
@@ -4272,16 +4272,21 @@
  village
+ type
 !%22);%0A   

Allow more village types during generation.