package com.censoredsoftware.censoredlib.data.location;

import com.google.common.base.Objects;
import org.bukkit.Bukkit;
import org.bukkit.Location;

public class Region
{
	public final static int REGION_LENGTH = 8;
	public final static int HALF_REGION_LENGTH = REGION_LENGTH / 2;

	private final int x;
	private final int z;
	private final String world;

	private Region(int x, int z, String world)
	{
		this.x = x;
		this.z = z;
		this.world = world;
	}

	public int getX()
	{
		return x;
	}

	public int getZ()
	{
		return z;
	}

	public String getWorld()
	{
		return world;
	}

	public Location getCenter()
	{
		return new Location(Bukkit.getWorld(world), x, 128, z);
	}

	public Region[] getSurroundingRegions()
	{
		Region[] area = new Region[9];
		area[0] = new Region(x - REGION_LENGTH, z - REGION_LENGTH, world);
		area[1] = new Region(x - REGION_LENGTH, z, world);
		area[2] = new Region(x - REGION_LENGTH, z + REGION_LENGTH, world);
		area[3] = new Region(x, z - REGION_LENGTH, world);
		area[4] = this;
		area[5] = new Region(x, z + REGION_LENGTH, world);
		area[6] = new Region(x + REGION_LENGTH, z - REGION_LENGTH, world);
		area[7] = new Region(x + REGION_LENGTH, z, world);
		area[8] = new Region(x + REGION_LENGTH, z + REGION_LENGTH, world);
		return area;
	}

	@Override
	public String toString()
	{
		return Objects.toStringHelper(this).add("world", world).add("x", x).add("z", z).toString();
	}

	@Override
	public int hashCode()
	{
		return Objects.hashCode(world, x, z);
	}

	@Override
	public boolean equals(Object object)
	{
		return Objects.equal(this, object);
	}

	public class X implements Comparable<X>
	{
		@Override
		public int compareTo(X regionX)
		{
			return x() == regionX.x() ? 0 : (x() > regionX.x() ? 1 : -1);
		}

		protected int x()
		{
			return getX();
		}
	}

	public class Z implements Comparable<Z>
	{
		@Override
		public int compareTo(Z regionZ)
		{
			return z() == regionZ.z() ? 0 : (z() > regionZ.z() ? 1 : -1);
		}

		protected int z()
		{
			return getZ();
		}
	}

	public static class Util
	{
		public static Region getRegion(Location location)
		{
			return new Region(getRegionCoordinate(location.getBlockX()), getRegionCoordinate(location.getBlockZ()), location.getWorld().getName());
		}

		public static Region getRegion(int X, int Z, String world)
		{
			return new Region(getRegionCoordinate(X), getRegionCoordinate(Z), world);
		}

		private static int getRegionCoordinate(int number)
		{
			int temp = number % REGION_LENGTH;
			if(temp >= HALF_REGION_LENGTH) return number + REGION_LENGTH - temp;
			return number - temp;
		}
	}
}

@@ -1790,24 +1790,84 @@
  getX();%0A%09%09%7D
+%0A%0A%09%09public Region getRegion()%0A%09%09%7B%0A%09%09%09return Region.this;%0A%09%09%7D
 %0A%09%7D%0A%0A%09public
@@ -2065,24 +2065,85 @@
 getZ();%0A%09%09%7D%0A
+%0A%0A%09%09public Region getRegion()%0A%09%09%7B%0A%09%09%09return Region.this;%0A%09%09%7D%0A
 %09%7D%0A%0A%09public 

Allow getting of Regions from the inner classes.