package bytecode;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

import org.apache.commons.bcel6.classfile.JavaClass;

import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.core.MyCompiler;
import de.dhbwstuttgart.core.MyCompilerAPI;
import de.dhbwstuttgart.logger.LoggerConfiguration;
import de.dhbwstuttgart.logger.Section;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.typeinference.ByteCodeResult;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
import de.dhbwstuttgart.typeinference.TypeinferenceResults;

public abstract class ASTBytecodeTest {	
	protected Class getClassToTest(){
		Class classToTest = null;
	    try {
			ClassLoader classLoader = getClassLoader();

		    classToTest =  classLoader.loadClass(getTestName());
		    

		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	    
	    return classToTest;
	}
	
	protected ClassLoader getClassLoader() throws Exception{
		File file = new File(getRootDirectory());
	    URL url = file.toURL();
	    URL[] urls = new URL[]{url};

	    return new URLClassLoader(urls);
	}
	
	public  ASTBytecodeTest(){
		LoggerConfiguration logConfig = new LoggerConfiguration().setOutput(Section.PARSER, System.out);
		MyCompilerAPI compiler = MyCompiler.getAPI(logConfig);
		try {
			TypeinferenceResults results = getResults();
			Menge<SourceFile> sourceFiles = new Menge<>();
			sourceFiles.add(getSourceFile());
			
			Menge<ByteCodeResult> bytecode = compiler.generateBytecode(sourceFiles, results);
			
			ByteCodeResult result = bytecode.firstElement();
			
			String rootDirectory = getRootDirectory();
			
			System.out.println(rootDirectory);
			
			JavaClass javaClass = result.getByteCode().getJavaClass();
			System.out.println(javaClass.toString());
			javaClass.dump(new File(rootDirectory+javaClass.getClassName()+".class"));			
			
			for(ClassGenerator cg: result.getByteCode().getExtraClasses().values()){
				JavaClass jc = cg.getJavaClass();
				jc.dump(new File(rootDirectory+jc.getClassName()+".class"));
			}
			
		}catch(Exception e){
			System.out.print(e.getMessage());
			throw new RuntimeException(e);
		}	
	}

	public SourceFile getSourceFile() {
		return new SourceFile();
	}

	public TypeinferenceResults getResults() {
		Menge<TypeinferenceResultSet> results = new Menge<>();
		results.add(new TypeinferenceResultSet(getSourceFile().KlassenVektor.get(0), new Menge(), new ResultSet()));
		
		return new TypeinferenceResults(results);
	}

	public String getRootDirectory() {
		return System.getProperty("user.dir")+"/test/bytecode/";
	}

	public String getTestName() {
		return "No Testname defined!";
	}
	
	
	
	
}