package ncrashed.warp.cores.actions;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import ncrashed.warp.ChunkCopier;
import ncrashed.warp.api.ICoreAction;
import ncrashed.warp.api.IWarpCore;
import net.minecraft.util.AxisAlignedBB;

public class ShortWarp implements ICoreAction 
{
	private class TempWarp
	{
		int dx, dy, dz;
		AxisAlignedBB box;
		
		public TempWarp(AxisAlignedBB box, int dx, int dy, int dz)
		{
			this.box = box;
			this.dx = dx;
			this.dy = dy;
			this.dz = dz;
		}
	}
	
	private boolean isCannotFindPlace = false;
	
	@Override
	public int getRequiredEnergy(IWarpCore core, int multCounter, int north,
			int south, int west, int east, int up, int down) 
	{
		AxisAlignedBB box = core.getCoreVolume().getBoundingBox(0, 0, 0);
		int summ = (int)(box.maxX-box.minX + box.maxY-box.minY + box.maxZ-box.minZ);
		
		return summ*2600;
	}

	@Override
	public boolean performAction(IWarpCore core, int multCounter, int north,
			int south, int west, int east, int up, int down) 
	{
		AxisAlignedBB boundingBox = core.getCoreVolume().getBoundingBox(core.getCoreX(), core.getCoreY(), core.getCoreZ());
		Iterator<AxisAlignedBB> iter = core.getCoreVolume().getBoxes(core.getCoreX(), core.getCoreY(), core.getCoreZ()).iterator();
		List<TempWarp> warpBoxes = new ArrayList<TempWarp>();
		isCannotFindPlace = false;
		
		while(iter.hasNext())
		{
			AxisAlignedBB box = iter.next();
			System.out.println("Warp box: "+box);
			
			int dx = 0;
			int dy = 0;
			int dz = 0;
			
			if(east-west > 0)
				dx = (int)(box.maxX-box.minX) + east-west;
			else if(east-west <0)
				dx = -(int)(box.maxX-box.minX) + east-west;
			
			if(up-down > 0)
				dy = (int)(box.maxY-box.minY) + up-down;
			else if(up-down < 0)
				dy = -(int)(box.maxY-box.minY) + up-down;
			
			if(south-north > 0)
				dz = (int)(box.maxZ-box.minZ) + south-north;
			else if(south-north < 0)
				dz = -(int)(box.maxZ-box.minZ) + south-north;
			
			dx *= multCounter;
			dy *= multCounter;
			dz *= multCounter;
			
			if(Math.abs(dx) > boundingBox.maxX-boundingBox.minX + 64) 
				dx = (int)(Math.signum(dx)*((boundingBox.maxX-boundingBox.minX) + 64));
			if(Math.abs(dy) > boundingBox.maxY-boundingBox.minY + 64) 
				dy = (int)(Math.signum(dy)*((boundingBox.maxY-boundingBox.minY) + 64));
			if(Math.abs(dz) > boundingBox.maxZ-boundingBox.minZ + 64) 
				dx = (int)(Math.signum(dy)*((boundingBox.maxZ-boundingBox.minZ) + 64));
			
			if(box.maxY + dy > 255) dy = 255 - (int)box.maxY;
			if(box.minY + dy < 0) dy = -(int)box.minY;
			
			System.out.println("Warp vector: ("+dx+","+dy+","+dz+")");
			
			AxisAlignedBB boxPlace = ChunkCopier.findEmptyPlace(core.getCoreWorld(), (int)box.minX, (int)box.minY, (int)box.minZ, (int)box.maxX, (int)box.maxY, (int)box.maxZ, dx, dy, dz);
			System.out.println("BoxPlace: "+boxPlace);
			if(boxPlace == null)
			{
				isCannotFindPlace = true;
				return false;
			}
			
			dx = (int)(boxPlace.minX - box.minX);
			dy = (int)(boxPlace.minY - box.minY);
			dz = (int)(boxPlace.minZ - box.minZ);
			System.out.println("Final warp vector: ("+dx+","+dy+","+dz+")");
			
			warpBoxes.add(new TempWarp(box, dx, dy, dz));
		}
		
		boolean result = true;
		ListIterator<TempWarp> tempIter = warpBoxes.listIterator();
		while(tempIter.hasNext())
		{
			TempWarp temp = tempIter.next();
			result = result && ChunkCopier.copyVolume(core.getCoreWorld(), (int)temp.box.minX, (int)temp.box.minY, (int)temp.box.minZ, 
					(int)temp.box.maxX, (int)temp.box.maxY, (int)temp.box.maxZ, temp.dx, temp.dy, temp.dz);
		}
		return result;
	}

	@Override
	public int getLowMultCounter() 
	{
		return 1;
	}

	@Override
	public int getHighMultCounter() 
	{
		return 7;
	}

	@Override
	public int getSuccessCooldown(IWarpCore core, int multCounter, int north,
			int south, int west, int east, int up, int down) 
	{
		AxisAlignedBB box = core.getCoreVolume().getBoundingBox(0, 0, 0);
		int summ = (int)(box.maxX-box.minX + box.maxY-box.minY + box.maxZ-box.minZ);
	
		return (summ/2500) + 2;
	}

	@Override
	public int getFailCooldown(IWarpCore core, int multCounter, int north,
			int south, int west, int east, int up, int down) 
	{
		return 5;
	}

	@Override
	public int getMinimumCooldown(IWarpCore core, int multCounter, int north,
			int south, int west, int east, int up, int down)
	{
		return 5;
	}

	@Override
	public boolean printActionResult() 
	{
		return true;
	}

	@Override
	public int getErrorBit() 
	{
		if(isCannotFindPlace) return 1;
		return 2;
	}
}
