import japa.parser.ast.body.ModifierSet;

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

import codeassess.javassessment.Assessor;
import codeassess.misc.Misc;

public class Template extends Assessor
{
	public Map<String, String> getConfig()
	{
		final Map<String, String> config = new Hashtable<String, String>();

		config.put("Language", "Java");
		config.put("Extensions", ".java");
		config.put("AssessmentMode", "SemiAutomatic");

		return config;
	}
	public List<Object[]> getProperties()
	{
		final List<Object[]> properties = new LinkedList<Object[]>();

		properties.add(new Object[]{ "GrupoDeALArrayListField", "Functionality", "librerias/implementacionesDeModelos/GrupoDeAL.java", "Comprueba que existe un atributo de tipo ArrayList<T>", "GrupoDeAL debe utilizar un atributo (ArrayList<T>) para los elementos del grupo", 1.0 });
		properties.add(new Object[]{ "GrupoDeALConstructor", "Functionality", "librerias/implementacionesDeModelos/GrupoDeAL.java", "Comprueba que el nombre y los argumentos del constructor", "Debe existir un constructor de la clase", 1.0 });
		properties.add(new Object[]{ "GrupoDeALAnyadeMethod", "Functionality", "librerias/implementacionesDeModelos/GrupoDeAL.java", "Comprueba que el nombre y los argumentos del método", "Debe existir el método anyade", 1.0 });
		properties.add(new Object[]{ "GrupoDeALExisteMethod", "Functionality", "librerias/implementacionesDeModelos/GrupoDeAL.java", "Comprueba que el nombre y los argumentos del método", "Debe existir el método existe", 2.5 });
		properties.add(new Object[]{ "GrupoDeALTallaMethod", "Functionality", "librerias/implementacionesDeModelos/GrupoDeAL.java", "Comprueba que el nombre y los argumentos del método", "Debe existir el método talla", 1.0 });
		properties.add(new Object[]{ "GrupoDeALEliminaMethod", "Functionality", "librerias/implementacionesDeModelos/GrupoDeAL.java", "Comprueba que el nombre y los argumentos del método", "Debe existir el método elimina", 2.5 });
		properties.add(new Object[]{ "GrupoDeALEsVacioMethod", "Functionality", "librerias/implementacionesDeModelos/GrupoDeAL.java", "Comprueba que el nombre y los argumentos del método", "Debe existir el método esVacio", 1.0 });

		return properties;
	}

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

		final TypeVariable<?>[] genericTypes = super.introspector.getGenericTypeParameters(grupoDeALClass);
		if (genericTypes.length == 0)
			return false;
		final TypeVariable<?> genericType = genericTypes[0];

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

			final Type fieldType = super.introspector.getType(field);
			final TypeVariable<?> fieldGenericType = super.introspector.getGenericType(fieldType, new int[] { 0 });
			if (fieldGenericType == null)
				continue;

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

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

		return false;
	}
	public boolean solveGrupoDeALArrayListField()
	{
		return false;
	}
	public boolean testGrupoDeALArrayListField()
	{
		return true;
	}

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

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

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

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

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

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

		return super.introspector.checkDeclaredMethod(grupoDeALClass, "anyade", paramsTypes, void.class, true);
	}
	public boolean solveGrupoDeALAnyadeMethod()
	{
		return false;
	}
	public boolean testGrupoDeALAnyadeMethod()
	{
		final String testCaseName = "Test02";
		final String testMethodName = "test";
		final Object result = super.tester.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.tester.executeTestCase(testClassName, test1MethodName);
		final Object result2 = super.tester.executeTestCase(testClassName, test2MethodName);

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

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

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

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

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

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

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

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

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

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

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

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

		final TypeVariable<?>[] genericTypes = super.introspector.getGenericTypeParameters(grupoDeALClass);
		if (genericTypes.length == 0)
			return false;
		final TypeVariable<?> genericType = genericTypes[0];

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

		final Type type = super.introspector.getReturnType(eliminaMethod);
		final TypeVariable<?> eliminaReturnType = super.introspector.getGenericType(type, new int[] { });
		if (eliminaReturnType == null)
			return false;

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

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

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

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

		final TypeVariable<?>[] genericTypes = super.introspector.getGenericTypeParameters(grupoDeALClass);
		if (genericTypes.length == 0)
			return false;
		final TypeVariable<?> genericType = genericTypes[0];

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

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

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

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