import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedList;
import net.minecraft.client.Minecraft;

public class DimensionBase {
	public static ArrayList<DimensionBase> list = new ArrayList<DimensionBase>();
	public static LinkedList<Integer> order = new LinkedList<Integer>();
	public final int number;
	public final Class<? extends xa> worldProvider;
	public final Class<? extends ur> teleporter;
	public String name = "Dimension";
	public String soundTrigger = "portal.trigger";
	public String soundTravel = "portal.travel";
	
	static {
		new DimensionOverworld();
		new DimensionNether();
	}

	public static DimensionBase getDimByNumber(int number) {
		for (int i = 0; i < list.size(); i++) {
			DimensionBase dim = (DimensionBase)list.get(i);
			if (dim.number == number) return dim;
		}
		return null;
	}
	public static DimensionBase getDimByProvider(Class<? extends xa> worldProvider) {
		for (int i = 0; i < list.size(); i++) {
			DimensionBase dim = (DimensionBase)list.get(i);
			if (dim.worldProvider.getName().equals(worldProvider.getName())) return dim;
		}
		return null;
	}

	public xa getWorldProvider() {
		try {
			return (xa)worldProvider.newInstance();
		} catch (InstantiationException localInstantiationException) {
		} catch (IllegalAccessException localIllegalAccessException) {}
		return null;
	}
	public ur getTeleporter() {
		try {
			if (teleporter != null) return (ur)teleporter.newInstance(); 
		} catch (InstantiationException localInstantiationException) {
		} catch (IllegalAccessException localIllegalAccessException) {}
		return null;
	}

	public static void respawn(boolean paramBoolean, int paramInt) {
		Minecraft localMinecraft = SAPI.getMinecraftInstance();

		if ((!localMinecraft.f.B) && (!localMinecraft.f.t.f()))
		{
			usePortal(0, true);
		}
		br localbp1 = null;
		br localbp2 = null;
		int i = 1;
		if ((localMinecraft.h != null) && (!paramBoolean))
		{
			localbp1 = localMinecraft.h.Q();
			if (localbp1 != null)
			{
				localbp2 = gs.a(localMinecraft.f, localbp1);
				if (localbp2 == null)
				{
					localMinecraft.h.b("tile.bed.notValid");
				}
			}
		}
		if (localbp2 == null)
		{
			localbp2 = localMinecraft.f.u();
			i = 0;
		}
		cl localcj = localMinecraft.f.w();
		if ((localcj instanceof kt))
		{
			kx localkt = (kx)localcj;
			localkt.d(localbp2.a >> 4, localbp2.c >> 4);
		}
		localMinecraft.f.d();
		localMinecraft.f.v();
		int j = 0;
		if (localMinecraft.h != null)
		{
			j = localMinecraft.h.aD;
			localMinecraft.f.e(localMinecraft.h);
		}
		localMinecraft.i = null;
		localMinecraft.h = ((dc)localMinecraft.c.b(localMinecraft.f));
		localMinecraft.h.m = paramInt;
		localMinecraft.i = localMinecraft.h;
		localMinecraft.h.t_();
		if (i != 0)
		{
			localMinecraft.h.a(localbp1);
			localMinecraft.h.c(localbp2.a + 0.5F, localbp2.b + 0.1F, localbp2.c + 0.5F, 0.0F, 0.0F);
		}
		localMinecraft.c.a(localMinecraft.h);
		localMinecraft.f.a(localMinecraft.h);
		localMinecraft.h.a = new lr(localMinecraft.z);
		localMinecraft.h.aD = j;
		localMinecraft.h.v();
		localMinecraft.c.b(localMinecraft.h);
		
		try {
			Method localMethod = Minecraft.class.getDeclaredMethod("d",String.class);
			localMethod.setAccessible(true);
			localMethod.invoke(localMinecraft,"Respawning");
		} catch (Exception localException) {localException.printStackTrace();}
		
		if ((localMinecraft.r instanceof ch))
		{
			localMinecraft.a((da)null);
		}
	}

	public static void usePortal(int dimNumber) {
		usePortal(dimNumber,false);
	}
	private static void usePortal(int dimNumber, boolean resetOrder) {
		Minecraft game = SAPI.getMinecraftInstance();

		int oldDimension = game.h.m;
		int newDimension = dimNumber;
		if (oldDimension == newDimension) newDimension = 0;

		game.f.e(game.h);
		game.h.be = false;

		Loc loc = new Loc(game.h.aM,game.h.aO);
		
		if (newDimension != 0) order.push(newDimension);
		if (newDimension == 0 && !order.isEmpty()) newDimension = order.pop();
		if (oldDimension == newDimension) newDimension = 0;
		
		String str = "";
		for (Integer dim : order) {
			if (!str.isEmpty()) str += ",";
			str += ""+dim;
		}

		fd world = null;
		DimensionBase dimOld = DimensionBase.getDimByNumber(oldDimension);
		DimensionBase dimNew = DimensionBase.getDimByNumber(newDimension);
		
		loc = dimOld.getDistanceScale(loc,true);
		loc = dimNew.getDistanceScale(loc,false);
		
		game.h.m = newDimension;
		game.h.c(loc.x,game.h.aN,loc.z,game.h.aS,game.h.aT);
		game.f.a(game.h,false);

		world = new fd(game.f,dimNew.getWorldProvider());
		game.a(world,(newDimension == 0 ? "Leaving" : "Entering")+" the "+(newDimension == 0 ? dimOld.name : dimNew.name),game.h);

		game.h.aI = game.f;
		game.h.c(loc.x,game.h.aN,loc.z,game.h.aS,game.h.aT);
		game.f.a(game.h,false);

		ur teleporter = dimNew.getTeleporter();
		if (teleporter == null) teleporter = dimOld.getTeleporter();
		teleporter.a(game.f,game.h);
	}

	public DimensionBase(int number, Class<? extends xa> worldProvider, Class<? extends ur> teleporter) {
		this.number = number;
		this.worldProvider = worldProvider;
		this.teleporter = teleporter;
		list.add(this);
	}

	public Loc getDistanceScale(Loc loc, boolean goingIn) {
		return loc;
	}
}