package ncrashed.warp.api;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.minecraft.world.World;

public class BigStructure implements IBigStructure 
{
	private Map<Integer, List<BlockInfo> > blockMap;
	private ArrayList<int[][]> layers;
	private Map<Integer, IConditionHandler> handlers;
	
	private int xSize;
	private int zSize;
	
	public BigStructure()
	{
		blockMap = new HashMap<Integer, List<BlockInfo> >();
		layers = new ArrayList<int[][]>();
		handlers = new HashMap<Integer, IConditionHandler>();
	}
	
	@Override
	public void addBlockMapping(Map<Integer, List<BlockInfo> > blockMap) 
	{
		this.blockMap = blockMap;
	}

	@Override
	public void addLayer(int[][] layer) 
	{
		if(layer == null || layer.length == 0 || layer[0].length == 0) return;
		
		if(layers.size() == 0)
		{
			layers.add(layer);
			zSize = layer.length;
			xSize = layer[0].length;
		} else
		{
			if(layer.length != zSize || layer[0].length != xSize) return;
			
			layers.add(layer);
		}
	}

	@Override
	public void addCondition(int recipeId, IConditionHandler handler)
	{
		handlers.put(recipeId, handler);
	}
	
	@Override
	public int getStructureX() 
	{
		return xSize;
	}

	@Override
	public int getStructureZ() 
	{
		return zSize;
	}

	@Override
	public int getStructureY()
	{
		return layers.size();
	}
	
	@Override
	public boolean checkStructure(World world, int x, int y, int z, int ox,
			int oy, int oz) 
	{
		//if(ox < 0 || oy < 0 || oz < 0) return false;
		//if(ox >= xSize || oy >= layers.size() || oz >= zSize) return false;
		
		for(int iy = 0; iy < layers.size(); ++iy)
		{
			for(int ix = 0; ix < xSize; ++ix)
			{
				for(int iz = 0; iz < zSize; ++iz)
				{
					int recipeID = layers.get(iy)[ix][iz];
					if(!isValidBlock(world.getBlockId(x+ix-ox, y+iy-oy, z+iz-oz), world.getBlockMetadata(x+ix-ox, y+iy-oy, z+iz-oz), ix, iy, iz)) return false;
					else if(handlers.containsKey(recipeID))
					{
						if(!handlers.get(recipeID).isValidBlock(world, x+ix-ox, y+iy-oy, z+iz-oz, recipeID)) return false;
					}
				}
			}
		}
		return true;
	}

	private boolean isValidBlock(int checkID, int checkMeta, int rx, int ry, int rz)
	{
		int recipeID = layers.get(ry)[rx][rz];
		
		if(recipeID == -1) return true;
		if(!blockMap.containsKey(recipeID) ) return false;
		
		List<BlockInfo> mapping = blockMap.get(recipeID);
		Iterator<BlockInfo> iter = mapping.iterator();
		while(iter.hasNext())
		{
			BlockInfo info = iter.next();
	
			if(info.id == checkID)
			{
				if(info.meta == -1 || info.meta == checkMeta) 
					return true;
			}
	
		}
		
		return false;
	}
	
}
