import japa.parser.ast.body.ModifierSet;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Hashtable;
import java.util.List;
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[]{ "PrismaCuadrangularExtendsCuadrado", "Functionality", "PrismaCuadrangular.java", "Debes utilizar \"extends\"", "PrismaCuadrangular debe heredar de la clase Cuadrado", 1.0 });
		properties.add(new Object[]{ "PrismaCuadrangularImplementsVolumen", "Functionality", "PrismaCuadrangular.java", "Debes utilizar \"implements\"", "PrismaCuadrangular debe implementar la interfaz Volumen", 1.0 });
		properties.add(new Object[]{ "PrismaCuadrangularAlturaField", "Functionality", "PrismaCuadrangular.java", "Comprueba que el atributo es de tipo double", "PrismaCuadrangular debe utilizar un único atributo (double) para la altura", 1.0 });
		properties.add(new Object[]{ "PrismaCuadrangularFirstConstructor", "Functionality", "PrismaCuadrangular.java", "Comprueba los argumentos del constructor", "Crear el constructor de la clase PrismaCuadrangular (double, double, double, double)", 1.5 });
		properties.add(new Object[]{ "PrismaCuadrangularSecondConstructor", "Functionality", "PrismaCuadrangular.java", "Comprueba los argumentos del constructor", "Crear el constructor de la clase PrismaCuadrangular (Cuadrado, double)", 1.5 });
		properties.add(new Object[]{ "PrismaCuadrangularVolumenMethod", "Functionality", "PrismaCuadrangular.java", "Comprueba el código del método", "Crear el método volumen de la clase PrismaCuadrangular", 1.0 });
		properties.add(new Object[]{ "GrupoFigurasVolumenMethod", "Functionality", "GrupoFiguras.java", "Comprueba el código del método", "Implementar el método volumen en la clase GrupoFiguras", 3.0 });

		return properties;
	}

	// PrismaCuadrangular extends Cuadrado
	public boolean checkPrismaCuadrangularExtendsCuadrado()
	{
		final Class<?> prismaCuadrangularClass = super.introspector.getClass("PrismaCuadrangular");
		final Class<?> cuadradoClass = super.introspector.getClass("Cuadrado");
		if (prismaCuadrangularClass == null || cuadradoClass == null)
			return false;

		return super.introspector.checkSuperclass(prismaCuadrangularClass, cuadradoClass);
	}
	public boolean solvePrismaCuadrangularExtendsCuadrado()
	{
		return false;
	}
	public boolean testPrismaCuadrangularExtendsCuadrado()
	{
		return true;
	}

	// PrismaCuadrangular implements Volumen
	public boolean checkPrismaCuadrangularImplementsVolumen()
	{
		final Class<?> prismaCuadrangularClass = super.introspector.getClass("PrismaCuadrangular");
		final Class<?> volumenClass = super.introspector.getClass("Volumen");
		if (prismaCuadrangularClass == null || volumenClass == null)
			return false;

		return super.introspector.getInterfaceCount(prismaCuadrangularClass) == 1 && super.introspector.checkImplements(prismaCuadrangularClass, volumenClass);
	}
	public boolean solvePrismaCuadrangularImplementsVolumen()
	{
		return false;
	}
	public boolean testPrismaCuadrangularImplementsVolumen()
	{
		return true;
	}

	// PrismaCuadrangular field
	public boolean checkPrismaCuadrangularAlturaField()
	{
		final Class<?> prismaCuadrangularClass = super.introspector.getClass("PrismaCuadrangular");
		if (prismaCuadrangularClass == null)
			return false;

		final Field[] prismaCuadrangularFields = super.introspector.getDeclaredFields(prismaCuadrangularClass);
		if (prismaCuadrangularFields.length != 1)
			return false;

		final Field prismaCuadrangularField = prismaCuadrangularFields[0];

		return super.introspector.checkClass(prismaCuadrangularField, double.class, true);
	}
	public boolean solvePrismaCuadrangularAlturaField()
	{
		return false;
	}
	public boolean testPrismaCuadrangularAlturaField()
	{
		return true;
	}

	// PrismaCuadrangular first constructor
	public boolean checkPrismaCuadrangularFirstConstructor()
	{
		final Class<?> prismaCuadrangularClass = super.introspector.getClass("PrismaCuadrangular");
		if (prismaCuadrangularClass == null)
			return false;

		final Class<?>[] paramTypesConstructor1 = { double.class, double.class, double.class, double.class };

		return super.introspector.checkDeclaredConstructor(prismaCuadrangularClass, paramTypesConstructor1, true);
	}
	public boolean solvePrismaCuadrangularFirstConstructor()
	{
		return false;
	}
	public boolean testPrismaCuadrangularFirstConstructor()
	{
		final String testCaseName = "Test02";
		final String testMethodName = "test";
		final Boolean expectedResult = true;
		final double posX = 12.3;
		final double posY = 56.6;
		final double lado = 415.8;
		final double altura = 922.5;

		final Object[] args = { posX, posY, lado, altura };
		final Object testCaseResult = super.tester.executeTestCase(testCaseName, testMethodName, args);

		return expectedResult.equals(testCaseResult);
	}

	// PrismaCuadrangular second constructor
	public boolean checkPrismaCuadrangularSecondConstructor()
	{
		final Class<?> prismaCuadrangularClass = super.introspector.getClass("PrismaCuadrangular");
		final Class<?> cuadradoClass = super.introspector.getClass("Cuadrado");
		if (prismaCuadrangularClass == null || cuadradoClass == null)
			return false;

		final Class<?>[] paramTypesConstructor = { cuadradoClass, double.class };

		return super.introspector.checkDeclaredConstructor(prismaCuadrangularClass, paramTypesConstructor, true);
	}
	public boolean solvePrismaCuadrangularSecondConstructor()
	{
		return false;
	}
	public boolean testPrismaCuadrangularSecondConstructor()
	{
		final String testCaseName = "Test03";
		final String testMethodName = "test";
		final Boolean expectedResult = true;
		final double posX = 12.3;
		final double posY = 56.6;
		final double lado = 415.8;
		final double altura = 922.5;

		final Object[] args = { posX, posY, lado, altura };
		final Object testCaseResult = super.tester.executeTestCase(testCaseName, testMethodName, args);

		return expectedResult.equals(testCaseResult);
	}

	// PrismaCuadrangular volumen method
	public boolean checkPrismaCuadrangularVolumenMethod()
	{
		final Class<?> prismaCuadrangularClass = super.introspector.getClass("PrismaCuadrangular");
		if (prismaCuadrangularClass == null)
			return false;

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

		return super.introspector.checkDeclaredMethod(prismaCuadrangularClass, "volumen", paramTypes, double.class, true);
	}
	public boolean solvePrismaCuadrangularVolumenMethod()
	{
		return false;
	}
	public boolean testPrismaCuadrangularVolumenMethod()
	{
		final String testCaseName = "Test01";
		final String testMethodName = "test";
		final Double expectedResult = 45.0;
		final double lado = 3.0;
		final double altura = 5.0;

		final Object[] args = { lado, altura };
		final Object testCaseResult = super.tester.executeTestCase(testCaseName, testMethodName, args);

		return expectedResult.equals(testCaseResult);
	}
	private double testPrismaCuadrangularVolumenMethod2()
	{
		final String testCaseName = "PrismaCuadrangularVolumen";
		final double passedPercentage = super.tester.executeTestCases(testCaseName);

		return Misc.round(passedPercentage, 2);
	}

	// GrupoFiguras volumen method
	public boolean checkGrupoFigurasVolumenMethod()
	{
		final Class<?> grupoFigurasClass = super.introspector.getClass("GrupoFiguras");
		if (grupoFigurasClass == null)
			return false;

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

		return super.introspector.checkDeclaredMethod(grupoFigurasClass, "volumen", paramTypes, double.class, true);
	}
	public boolean solveGrupoFigurasVolumenMethod()
	{
		return false;
	}
	public boolean testGrupoFigurasVolumenMethod()
	{
		final String testCaseName = "Test04";
		final String testMethodName = "test";
		final Double expectedResult = 137.0;
		final Object testCaseResult = super.tester.executeTestCase(testCaseName, testMethodName);

		return expectedResult.equals(testCaseResult);
	}
	private double testGrupoFigurasVolumenMethod2()
	{
		final String testCaseName = "GrupoFigurasVolumen";
		final double passedPercentage = super.tester.executeTestCases(testCaseName);

		return Misc.round(passedPercentage, 2);
	}
}