/*
 * This file is part of Dynamic Surroundings, licensed under the MIT License (MIT).
 *
 * Copyright (c) OreCruncher
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package org.blockartistry.mod.DynSurround.registry;

import java.io.InputStream;
import java.util.List;

import javax.annotation.Nonnull;

import org.blockartistry.mod.DynSurround.DSurround;
import org.blockartistry.mod.DynSurround.client.event.RegistryEvent;

import com.google.common.collect.ImmutableList;

import net.minecraft.client.Minecraft;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.relauncher.Side;

public class RegistryManager {

	public static enum RegistryType {
		SOUND(0), BIOME(1), BLOCK(2), DIMENSION(3), FOOTSTEPS(4), SEASON(5), ITEMS(6);

		private final int id;

		RegistryType(final int id) {
			this.id = id;
		}

		public int getId() {
			return this.id;
		}
	}

	private static final RegistryManager[] managers = { null, null };

	static RegistryManager getManager() {
		final Side side = DSurround.proxy().effectiveSide();
		if(side == Side.CLIENT) {
			if(managers[1] == null) {
				managers[1] = new RegistryManagerClient();
				managers[1].reload();
			}
			return managers[1];
		} else {
			if(managers[0] == null) {
				managers[0] = new RegistryManager();
				managers[0].reload();
			}
			return managers[0];
		}
	}

	@SuppressWarnings("unchecked")
	public static <T extends Registry> T get(@Nonnull RegistryType type) {
		return (T) getManager().getRegistry(type);
	}

	public static void reloadResources() {
		// Reload the server side.  This should be called
		// by the server thread and not the client because
		// the /ds command runs server side.
		if (managers[0] != null) {
			managers[0].reload();
		}
		
		// Schedule reload on the client thread.  If this is a
		// dedicated server there won't be a ResourceManager for
		// this array slot thus it won't pass the test.
		if (managers[1] != null) {
			Minecraft.getMinecraft().addScheduledTask(new Runnable() {
				public void run() {
					managers[1].reload();
				}
			});
		}
	}

	protected final Side side;
	protected final Registry[] registries = new Registry[RegistryType.values().length];
	
	RegistryManager() {
		this(Side.SERVER);
	}

	RegistryManager(final Side side) {
		this.side = side;
		this.registries[RegistryType.DIMENSION.getId()] = new DimensionRegistry(side);
		this.registries[RegistryType.BIOME.getId()] = new BiomeRegistry(side);
		this.registries[RegistryType.SOUND.getId()] = new SoundRegistry(side);
		this.registries[RegistryType.SEASON.getId()] = new SeasonRegistry(side);
	}

	void reload() {
		for (final Registry r : this.registries)
			if(r != null)
				r.init();

		new DataScripts(this.side).execute(getAdditionalScripts());

		for (final Registry r : this.registries)
			if(r != null)
				r.initComplete();

		MinecraftForge.EVENT_BUS.post(new RegistryEvent.Reload(this.side));
	}

	@SuppressWarnings("unchecked")
	public <T> T getRegistry(final RegistryType type) {
		return (T) this.registries[type.getId()];
	}

	public List<InputStream> getAdditionalScripts() {
		return ImmutableList.of();
	}

}

@@ -1335,60 +1335,8 @@
 l;%0A%0A
-import org.blockartistry.mod.DynSurround.DSurround;%0A
 impo
@@ -1538,16 +1538,71 @@
 tForge;%0A
+import net.minecraftforge.fml.common.FMLCommonHandler;%0A
 import n
@@ -2049,27 +2049,40 @@
 e = 
-DSurround.proxy().e
+FMLCommonHandler.instance().getE
 ffec
@@ -2097,16 +2097,17 @@
 ();%0A%09%09if
+ 
 (side ==
@@ -2119,32 +2119,33 @@
 .CLIENT) %7B%0A%09%09%09if
+ 
 (managers%5B1%5D == 
@@ -2269,16 +2269,17 @@
  %7B%0A%09%09%09if
+ 
 (manager
@@ -2606,37 +2606,11 @@
 oad 
-the server side.  This should
+can
  be 
@@ -2619,327 +2619,277 @@
 lled
-%0A%09%09// by 
+ on ei
 the
+r
  s
-erver thread and not the client because%0A%09%09// the /ds command runs server side.%0A%09%09if (managers%5B0%5D != null) %7B%0A%09%09%09managers%5B0%5D.reload();%0A%09%09%7D%0A%09%09%0A%09%09// Schedule reload on the client thread.  If this is a%0A%09%09// dedicated server there won't be a ResourceManager for%0A%09%09// this array slot thus it won't pass the test.
+ide so make sure we queue%0A%09%09// up a scheduled task appropriately.%0A%09%09if (managers%5B0%5D != null) %7B%0A%09%09%09FMLCommonHandler.instance().getMinecraftServerInstance().addScheduledTask(new Runnable() %7B%0A%09%09%09%09public void run() %7B%0A%09%09%09%09%09managers%5B0%5D.reload();%0A%09%09%09%09%7D%0A%09%09%09%7D);%0A%09%09%7D%0A
 %0A%09%09i
@@ -3161,17 +3161,16 @@
 ength%5D;%0A
-%09
 %0A%09Regist
@@ -3627,32 +3627,33 @@
 egistries)%0A%09%09%09if
+ 
 (r != null)%0A%09%09%09%09
@@ -3774,16 +3774,17 @@
 s)%0A%09%09%09if
+ 
 (r != nu

Fix startup race condition where proxy is not yet available