import japa.parser.ast.body.ModifierSet;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import assessment.evaluator.Evaluation;
import assessment.evaluator.Evaluator;
import assessment.evaluator.Generator;
import misc.Misc;

public class Template extends Evaluator
{
	// Implements Evaluator
	protected List<Evaluation> getEvaluations()
	{
		final List<Evaluation> evaluations = new LinkedList<Evaluation>();

		evaluations.add(new Evaluation("GrupoDeALArrayListField", "librerias.implementacionesDeModelos.GrupoDeAL", "elementos", "GrupoDeAL debe utilizar un atributo (ArrayList<T>) para los elementos del grupo", 1.0));
		evaluations.add(new Evaluation("GrupoDeALConstructor", "librerias.implementacionesDeModelos.GrupoDeAL", "Crear el constructor", 1.0));
		evaluations.add(new Evaluation("GrupoDeALAnyadeMethod", "librerias.implementacionesDeModelos.GrupoDeAL", "anyade", "T", "Crear el método anyade", 1.0));
		evaluations.add(new Evaluation("GrupoDeALExisteMethod", "librerias.implementacionesDeModelos.GrupoDeAL", "existe", "T", "Crear el método existe", 2.5));
		evaluations.add(new Evaluation("GrupoDeALTallaMethod", "librerias.implementacionesDeModelos.GrupoDeAL", "talla", "", "Crear el método talla", 1.0));
		evaluations.add(new Evaluation("GrupoDeALEliminaMethod", "librerias.implementacionesDeModelos.GrupoDeAL", "elimina", "T", "Crear el método elimina", 2.5));
		evaluations.add(new Evaluation("GrupoDeALEsVacioMethod", "librerias.implementacionesDeModelos.GrupoDeAL", "esVacio", "", "Crear el método esVacio", 1.0));

		return evaluations;
	}
	protected List<Generator> getTestCasesToGenerate()
	{
		List<Generator> testCasesToGenerate = new ArrayList<Generator>();
		int numTestCases = 3;

		testCasesToGenerate.add(new Generator("Constructor", "GrupoDeAL", "GrupoDeAL", new Class<?>[] { }, void.class, 1, null, null));
		testCasesToGenerate.add(new Generator("Anyadir", "librerias.implementacionesDeModelos.GrupoDeAL", "anyade", new Class<?>[] { Object.class }, void.class, numTestCases, null, null));
		testCasesToGenerate.add(new Generator("Existe", "GrupoDeAL", "existe", new Class<?>[] { Integer.class }, boolean.class, numTestCases, null, null));
		testCasesToGenerate.add(new Generator("Talla", "GrupoDeAL", "talla", new Class<?>[] { }, int.class, numTestCases, null, null));
		testCasesToGenerate.add(new Generator("Elimina", "GrupoDeAL", "elimina", new Class<?>[] { Integer.class }, Integer.class, numTestCases, null, null));
		testCasesToGenerate.add(new Generator("Vacio", "GrupoDeAL", "esVacio", new Class<?>[] { }, boolean.class, numTestCases, null, null));

//		return testCasesToGenerate;
		return null;
	}

	// PilaAL has ArrayList field
	public boolean checkGrupoDeALArrayListField()
	{
		final Class<?> grupoDeALClass = super.inspector.getClass("librerias.implementacionesDeModelos.GrupoDeAL");
		if (grupoDeALClass == null)
			return false;

		final TypeVariable<?> genericType = super.inspector.getGenericParameter(grupoDeALClass, 0);
		if (genericType == null)
			return false;

		for (Field field : super.inspector.getDeclaredFields(grupoDeALClass))
		{
			if (!super.inspector.checkType(field, ArrayList.class, false))
				continue;

			final TypeVariable<?> fieldGenericType = super.inspector.getGenericType(field, 0);
			if (fieldGenericType == null)
				continue;

			if (super.inspector.checkSameGenericTypes(fieldGenericType, genericType))
				return true;
		}

		final Class<?> grupoDeALSuperclass = super.inspector.getSuperclass(grupoDeALClass);
		if (grupoDeALSuperclass != null)
			if (super.inspector.checkSameClasses(grupoDeALSuperclass, ArrayList.class))
				return true;

		return false;
	}

	// PilaAL has constructor
	public boolean checkGrupoDeALConstructor()
	{
		final Class<?> grupoDeALClass = super.inspector.getClass("librerias.implementacionesDeModelos.GrupoDeAL");
		if (grupoDeALClass == null)
			return false;

		final Class<?>[] paramsTypes = { };

		return super.inspector.checkDeclaredConstructor(grupoDeALClass, paramsTypes, false);
	}
	public boolean testGrupoDeALConstructor()
	{
		final String testCaseName = "Test01";
		final String testMethodName = "test";
		final Object result = super.test.executeTestCase(testCaseName, testMethodName);

		return result == null ? false : (Boolean) result;
	}

	// PilaAL anyade method
	public boolean checkGrupoDeALAnyadeMethod()
	{
		final Class<?> grupoDeALClass = super.inspector.getClass("librerias.implementacionesDeModelos.GrupoDeAL");
		if (grupoDeALClass == null)
			return false;

		final Class<?>[] paramsTypes = { Object.class };

		return super.inspector.checkDeclaredMethod(grupoDeALClass, "anyade", paramsTypes, void.class, true);
	}
	public boolean testGrupoDeALAnyadeMethod()
	{
		final String testCaseName = "Test02";
		final String testMethodName = "test";
		final Object result = super.test.executeTestCase(testCaseName, testMethodName);

		return result == null ? false : (Boolean) result;
	}
	public boolean testGrupoDeALAnyadeMethod2()
	{
		final String testClassName = "GrupoDeALTest";
		final String test1MethodName = "testAnyadeExiste";
		final String test2MethodName = "testAnyadeElimina";
		final Object result1 = super.test.executeTestCase(testClassName, test1MethodName);
		final Object result2 = super.test.executeTestCase(testClassName, test2MethodName);

		return result1 == null || result2 == null ? false : (Boolean) result1 && (Boolean) result2;
	}

	// PilaAL exists method
	public boolean checkGrupoDeALExisteMethod()
	{
		final Class<?> grupoDeALClass = super.inspector.getClass("librerias.implementacionesDeModelos.GrupoDeAL");
		if (grupoDeALClass == null)
			return false;

		final Class<?>[] paramsTypes = { Object.class };

		return super.inspector.checkDeclaredMethod(grupoDeALClass, "existe", paramsTypes, boolean.class, true);
	}
	public boolean testGrupoDeALExisteMethod()
	{
		final String testCaseName = "Test03";
		final String testMethodName = "test";
		final Object result = super.test.executeTestCase(testCaseName, testMethodName);

		return result == null ? false : (Boolean) result;
	}
	public boolean testGrupoDeALExisteMethod2()
	{
		final String testClassName = "GrupoDeALTest";
		final String testMethodName = "testAnyadeExiste";
		final Object result = super.test.executeTestCase(testClassName, testMethodName);

		return result == null ? false : (Boolean) result;
	}

	// PilaAL talla method
	public boolean checkGrupoDeALTallaMethod()
	{
		final Class<?> grupoDeALClass = super.inspector.getClass("librerias.implementacionesDeModelos.GrupoDeAL");
		if (grupoDeALClass == null)
			return false;

		final Class<?>[] paramsTypes = {  };

		return super.inspector.checkDeclaredMethod(grupoDeALClass, "talla", paramsTypes, int.class, false);
	}
	public boolean testGrupoDeALTallaMethod()
	{
		final String testCaseName = "Test04";
		final String testMethodName = "test";
		final Object result = super.test.executeTestCase(testCaseName, testMethodName);

		return result == null ? false : (Boolean) result;
	}
	public boolean testGrupoDeALTallaMethod2()
	{
		final String testClassName = "GrupoDeALTest";
		final String testMethodName = "testVacioTalla";
		final Object result = super.test.executeTestCase(testClassName, testMethodName);

		return result == null ? false : (Boolean) result;
	}

	// PilaAL elimina method
	public boolean checkGrupoDeALEliminaMethod()
	{
		final Class<?> grupoDeALClass = super.inspector.getClass("librerias.implementacionesDeModelos.GrupoDeAL");
		if (grupoDeALClass == null)
			return false;

		final TypeVariable<?> genericType = super.inspector.getGenericParameter(grupoDeALClass, 0);
		if (genericType == null)
			return false;

		final Class<?>[] paramTypes = { Object.class };
		final Method eliminaMethod = super.inspector.getDeclaredMethod(grupoDeALClass, "elimina", paramTypes, true);
		if (eliminaMethod == null)
			return false;

		final TypeVariable<?> eliminaReturnType = super.inspector.getGenericReturnType(eliminaMethod);
		if (eliminaReturnType == null)
			return false;

		return super.inspector.checkSameGenericTypes(eliminaReturnType, genericType);
	}
	public boolean testGrupoDeALEliminaMethod()
	{
		final String testCaseName = "Test05";
		final String testMethodName = "test";
		final Object result = super.test.executeTestCase(testCaseName, testMethodName);

		return result == null ? false : (Boolean) result;
	}
	public boolean testGrupoDeALEliminaMethod2()
	{
		final String testClassName = "GrupoDeALTest";
		final String testMethodName = "testAnyadeElimina";
		final Object result = super.test.executeTestCase(testClassName, testMethodName);

		return result == null ? false : (Boolean) result;
	}

	// PilaAL esVacio method
	public boolean checkGrupoDeALEsVacioMethod()
	{
		final Class<?> grupoDeALClass = super.inspector.getClass("librerias.implementacionesDeModelos.GrupoDeAL");
		if (grupoDeALClass == null)
			return false;

		final TypeVariable<?> genericType = super.inspector.getGenericParameter(grupoDeALClass, 0);
		if (genericType == null)
			return false;

		final Class<?>[] paramsTypes = { };

		return super.inspector.checkDeclaredMethod(grupoDeALClass, "esVacio", paramsTypes, boolean.class, false);
	}
	public boolean testGrupoDeALEsVacioMethod()
	{
		final String testCaseName = "Test06";
		final String testMethodName = "test";
		final Object result = super.test.executeTestCase(testCaseName, testMethodName);

		return result == null ? false : (Boolean) result;
	}
	public boolean testGrupoDeALEsVacioMethod2()
	{
		final String testClassName = "GrupoDeALTest";
		final String testMethodName = "testVacioTalla";
		final Object result = super.test.executeTestCase(testClassName, testMethodName);

		return result == null ? false : (Boolean) result;
	}
}