/*
 * Copyright 2016 FabricMC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.fabricmc.loader.language;

import net.fabricmc.api.EnvType;
import net.fabricmc.loader.FabricLoader;
import net.fabricmc.loader.launch.common.FabricLauncherBase;
import org.objectweb.asm.ClassReader;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class JavaLanguageAdapter implements LanguageAdapter {
	private static boolean canApplyInterface(String itfString) throws IOException {
		String className = itfString.replace('.', '/') + ".class";
		ClassReader reader = new ClassReader(FabricLauncherBase.getLauncher().getResourceAsStream(className));

		// TODO: Be a bit more involved
		if (className.equals("net.fabricmc.api.ClientModInitializer")) {
			if (FabricLoader.INSTANCE.getEnvironmentHandler().getEnvironmentType() == EnvType.SERVER) {
				return false;
			}
		} else if (className.equals("net.fabricmc.api.DedicatedServerModInitializer")) {
			if (FabricLoader.INSTANCE.getEnvironmentHandler().getEnvironmentType() == EnvType.CLIENT) {
				return false;
			}
		}

		for (String s : reader.getInterfaces()) {
			if (!canApplyInterface(s)) {
				return false;
			}
		}

		return true;
	}

	public static Class<?> getClass(String classString, Options options) throws ClassNotFoundException, IOException {
		String className = classString.replace('.', '/') + ".class";
		ClassReader reader = new ClassReader(FabricLauncherBase.getLauncher().getResourceAsStream(className));
		for (String s : reader.getInterfaces()) {
			if (!canApplyInterface(s)) {
				switch (options.getMissingSuperclassBehavior()) {
					case RETURN_NULL:
						return null;
					case CRASH:
					default:
						throw new ClassNotFoundException("Could not find or load class " + s);

				}
			}
		}

		return Class.forName(classString);
	}

	@Override
	public Object createInstance(Class<?> modClass, Options options) throws LanguageAdapterException {
		try {
			Constructor<?> constructor = modClass.getDeclaredConstructor();
			return constructor.newInstance();
		} catch (NoSuchMethodException e) {
			throw new LanguageAdapterException("Could not find constructor for class " + modClass.getName() + "!", e);
		} catch (IllegalAccessException e) {
			throw new LanguageAdapterException("Could not access constructor of class " + modClass.getName() + "!", e);
		} catch (InvocationTargetException | IllegalArgumentException | InstantiationException e) {
			throw new LanguageAdapterException("Could not instantiate class " + modClass.getName() + "!", e);
		}
	}
}

@@ -1153,113 +1153,8 @@
 ss%22;
-%0A%09%09ClassReader reader = new ClassReader(FabricLauncherBase.getLauncher().getResourceAsStream(className));
 %0A%0A%09%09
@@ -1187,37 +1187,45 @@
 olved%0A%09%09
-if (className.equals(
+switch (itfString) %7B%0A%09%09%09case 
 %22net.fab
@@ -1247,37 +1247,35 @@
 tModInitializer%22
-)) %7B%0A
+:%0A%09
 %09%09%09if (FabricLoa
@@ -1349,32 +1349,33 @@
 e.SERVER) %7B%0A%09%09%09%09
+%09
 return false;%0A%09%09
@@ -1376,43 +1376,33 @@
 se;%0A
+%09
 %09%09%09%7D%0A%09%09
-%7D else if (className.equals(
+%09%09break;%0A%09%09%09case 
 %22net
@@ -1445,21 +1445,19 @@
 ializer%22
-)) %7B%0A
+:%0A%09
 %09%09%09if (F
@@ -1539,32 +1539,33 @@
 e.CLIENT) %7B%0A%09%09%09%09
+%09
 return false;%0A%09%09
@@ -1565,23 +1565,130 @@
 lse;%0A%09%09%09
+%09
 %7D%0A%09%09%7D%0A%0A
+%09%09ClassReader reader = new ClassReader(FabricLauncherBase.getLauncher().getResourceAsStream(className));%0A%0A
 %09%09for (S

Test the right string and clean up a bit (#47)