package bytecode;

import static org.junit.Assert.*;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Vector;

import org.junit.BeforeClass;
import org.junit.Test;

import de.dhbwstuttgart.core.JavaTXCompiler;

public class MatrixTest {
	private static String path;
	private static File fileToTest;
	private static JavaTXCompiler compiler;
	private static ClassLoader loader;
	private static Class<?> classToTest;
	private static String pathToClassFile;
	private static Object instanceOfClass_m1;
	private static Object instanceOfClass_m2;
	private static Object instanceOfClass_m3;

	@Test
	public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IOException, InstantiationException {
		path = System.getProperty("user.dir")+"/src/test/resources/bytecode/javFiles/Matrix.jav";
		fileToTest = new File(path);
		compiler = new JavaTXCompiler(fileToTest);
		pathToClassFile = System.getProperty("user.dir")+"/src/test/resources/testBytecode/generatedBC/";
		compiler.generateBytecode(pathToClassFile);
		loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
		classToTest = loader.loadClass("Matrix"); 
		
		Vector<Vector<Integer>> vv = new Vector<Vector<Integer>>();
		 Vector<Integer> v1 = new Vector<Integer> ();
		 v1.addElement(2);
		 v1.addElement(2);
		 Vector<Integer> v2 = new Vector<Integer> ();
		 v2.addElement(3);
		 v2.addElement(3);
		 //Matrix m1 = new Matrix();
		 //m1.addElement(v1);
		 //m1.addElement(v2);
		 vv.addElement(v1);
		 vv.addElement(v2);
		 instanceOfClass_m1 = classToTest.getDeclaredConstructor(Vector.class).newInstance(vv);  //Matrix m1 = new Matrix(vv);

		 Vector<Vector<Integer>> vv1 = new Vector<Vector<Integer>>();
		 Vector<Integer> v3 = new Vector<Integer> ();
		 v3.addElement(2);
		 v3.addElement(2);
		 Vector<Integer> v4 = new Vector<Integer> ();
		 v4.addElement(3);
		 v4.addElement(3);
		 //Matrix m2 = new Matrix();
		 //m2.addElement(v3);
		 //m2.addElement(v4);
		 vv1.addElement(v3);
		 vv1.addElement(v4);
		 instanceOfClass_m2 = classToTest.getDeclaredConstructor(Vector.class).newInstance(vv1);//Matrix m2 = new Matrix(vv1);
		 
		 

		 //Matrix m3 = m1.mul(vv1);
		 Method mul = classToTest.getDeclaredMethod("mul", Vector.class);
		 Object result = mul.invoke(instanceOfClass_m1, instanceOfClass_m2);
		 System.out.println(instanceOfClass_m1.toString() + " * " + instanceOfClass_m2.toString() + " = " + result.toString());
		
		 Vector<Vector<Integer>> res = new Vector<Vector<Integer>>();
		 Vector<Integer> v5 = new Vector<Integer> ();
		 v5.addElement(10);
		 v5.addElement(10);
		 Vector<Integer> v6 = new Vector<Integer> ();
		 v6.addElement(15);
		 v6.addElement(15);
		 //Matrix m2 = new Matrix();
		 //m2.addElement(v3);
		 //m2.addElement(v4);
		 res.addElement(v5);
		 res.addElement(v6);
		 instanceOfClass_m3 = classToTest.getDeclaredConstructor(Vector.class).newInstance(res);
		 assertEquals(result, instanceOfClass_m3);
	}

}
