package org.bench4q.recorder.httpcapture.generator;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.bench4q.recorder.httpcapture.Config;
import org.bench4q.recorder.httpcapture.IScriptAdapter;
import org.bench4q.recorder.httpcapture.Utils;

public class GeneratorFactory {
	private static Config config = Config.getConfig();
	public static final String GENERATOR_CLASSNAMES_PROPERTY = "generator.classnames";
	public static final String JYTHON_CLASSNAME = "com.bitmechanic.maxq.generator.JythonCodeGenerator";

	public static String[] getClasses() {
		String names = config.getProperty("generator.classnames",
				"com.bitmechanic.maxq.generator.JythonCodeGenerator");
		return Utils.splitString(names, ":");
	}

	public static String getClassDescription(String className)
			throws ClassNotFoundException, IllegalAccessException,
			InvocationTargetException {
		Method getGenDesc;
		Class<?> gen = Class.forName(className);
		try {
			getGenDesc = gen.getMethod("getGeneratorDescription", gen);
		} catch (NoSuchMethodException e) {
			return className;
		}

		return (String) getGenDesc.invoke((Object) null, (Object) null);
	}

	public static IScriptGenerator newGenerator(String className,
			IScriptAdapter adapter) {
		Class<?> clazz = null;
		try {
			clazz = GeneratorFactory.class.getClassLoader()
					.loadClass(className);
		} catch (ClassNotFoundException e) {
			throw new IllegalStateException(
					"Invalid test script class specified .  Class not found:"
							+ className);
		}

		if (IScriptGenerator.class.isAssignableFrom(clazz)) {
			try {
				Class<?>[] generatorConstructorParameterClasses = { IScriptAdapter.class };
				Object[] generatorConstructorParameters = { adapter };
				Constructor<?> constructor = clazz
						.getDeclaredConstructor(generatorConstructorParameterClasses);
				return (IScriptGenerator) constructor
						.newInstance(generatorConstructorParameters);
			} catch (NoSuchMethodException e) {
				throw new IllegalStateException(
						"Invalid test script class specified.  Must have a constructor that takes in properties: "
								+ className);
			} catch (InstantiationException e) {
				throw new IllegalStateException(
						"Invalid test script class specified.  Could not construct: "
								+ className);
			} catch (InvocationTargetException e) {
				e.printStackTrace();
				throw new IllegalStateException(
						"Invalid test script class specified.  Exception thrown in constructor: "
								+ className);
			} catch (IllegalAccessException e) {
				throw new IllegalStateException(
						"Invalid test script class specified.  IllegalAccessException: "
								+ className);
			}
		}
		throw new IllegalStateException(
				"Invalid test script class specified.  Does not implement IScriptGenerator: "
						+ className);
	}
}
