package org.spideruci.tacoco;

import static org.spideruci.tacoco.cli.CliAble.DB;
import static org.spideruci.tacoco.cli.CliAble.HOME;
import static org.spideruci.tacoco.cli.CliAble.OUTDIR;
import static org.spideruci.tacoco.cli.CliAble.SUT;
import static org.spideruci.tacoco.cli.CliAble.AnalyzerCli.readArgumentValue;
import static org.spideruci.tacoco.cli.CliAble.AnalyzerCli.readOptionalArgumentValue;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

import org.spideruci.tacoco.AbstractBuildProbe.Child;
import org.spideruci.tacoco.db.CreateSQLiteDB;

public class TacocoLauncher {

	private String tacocoHome, targetDir;
	private static String tacocoClasspath = null;

	private TacocoLauncher(String tacocoHome, String targetDir){
		this.tacocoHome = tacocoHome;
		this.targetDir = targetDir;
	}

	public static void main(String[] args) throws Exception{

		TacocoLauncher launcher = new TacocoLauncher(readOptionalArgumentValue(HOME,System.getProperty("user.dir"))
													,readArgumentValue(SUT));
		AbstractBuildProbe probe = AbstractBuildProbe.getInstance(launcher.targetDir);
		
		launcher.setTacocoEnv();
		String parentCP = probe.getClasspath() +":"+ launcher.getTacocoClasspath(); 

		if(probe.hasChild()){	
			for(Child child : probe.getChildren()){
				launcher.startJUnitRunner(child.id, child.classpath+":"+ parentCP, child.targetDir, child.jvmArgs);
			}
		}
		launcher.startJUnitRunner(probe.getId(), parentCP, launcher.targetDir, null);
	}

	
	private void startJUnitRunner(String id, String classpath, String targetDir, String[] jvmArgs) {
		
		String outdir = readOptionalArgumentValue(OUTDIR, tacocoHome+"/tacoco_output");
		
		if(!new File(outdir).exists()) new File(outdir).mkdirs();
		
		//delete files before execution, 
		File exec = new File(outdir, id+".exec");
		File err = new File(outdir, id+".err");
		File log = new File(outdir, id+".log");
		if(exec.exists()) exec.delete();
		if(err.exists()) err.delete();
		if(log.exists()) log.delete();
		
		
		ProcessBuilder builder = new ProcessBuilder(
				"java",
				"-cp", classpath,
				"-Xmx1536M",// "-Duser.language=hi", "-Duser.country=IN",
				"-javaagent:"+tacocoHome+"/lib/org.jacoco.agent-0.7.4.201502262128-runtime.jar=destfile="+outdir+"/"+id+".exec,dumponexit=false",
				"-Dtacoco.sut="+targetDir,
				"-Dtacoco.output="+outdir,
				"-Dtacoco.log=off",
				"-Dtacoco.thread="+1,
				"org.spideruci.tacoco.JUnitRunner");//.inheritIO();
		builder.directory(new File(targetDir));
		builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
		builder.redirectError(err);
		builder.redirectOutput(log);
		
		final Process p;
		try{
			p= builder.start();
			Runtime.getRuntime().addShutdownHook(new Thread() {
			    public void run() {
			        p.destroy();
			    }
			}); 
			p.waitFor();
		}catch(Exception e){
			e.printStackTrace();
		}
		String dbFile = outdir+"/tacoco.db";
		if(System.getProperties().containsKey(DB))
			try {
				CreateSQLiteDB.dump(dbFile, targetDir, exec.toString());
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}

	private String getTacocoClasspath() throws Exception{
		
		if(tacocoClasspath != null) return tacocoClasspath;
		if(!new File(tacocoHome+"/cp.txt").exists()) {
			ProcessBuilder builder = new ProcessBuilder(
					"/usr/bin/mvn","dependency:build-classpath","-Dmdep.outputFile=cp.txt").inheritIO();
			builder.directory(new File(tacocoHome));
			Process p = builder.start();
			p.waitFor();
		}
		tacocoClasspath = new String(Files.readAllBytes(Paths.get("cp.txt")))+":"+ tacocoHome + "/target/classes";
		return tacocoClasspath;
	}

	/*
	 * Move jacoco.jar from mvn repo to tacocoHome/lib
	 */
	private void setTacocoEnv() {
		if(new File(tacocoHome+"/lib").exists()) return;
		ProcessBuilder builder = new ProcessBuilder("/usr/bin/mvn","dependency:copy-dependencies","-DoutputDirectory=lib").inheritIO();
		builder.directory(new File(tacocoHome));
		try{
			Process p = builder.start();
			p.waitFor();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
}

@@ -75,16 +75,69 @@
 ble.DB;%0A
+import static org.spideruci.tacoco.cli.CliAble.EXEC;%0A
 import s
@@ -181,16 +181,16 @@
 e.HOME;%0A
-
 import s
@@ -936,16 +936,153 @@
 ception%7B
+%0A%09%09%0A%09%09String targetDir = readArgumentValue(SUT);%0A%09%09if(targetDir.endsWith(%22/%22)) targetDir = targetDir.substring(0, targetDir.length());%0A%09%09
 %0A%0A%09%09Taco
@@ -1199,38 +1199,25 @@
 %09%09%09%09%09%09%09,
-readArgumentValue(SUT)
+targetDir
 );%0A%09%09Abs
@@ -1852,16 +1852,81 @@
 tput%22);%0A
+%09%09String execFile = readOptionalArgumentValue(EXEC, id+%22.exec%22);%0A
 %09%09%0A%09%09if(
@@ -2050,26 +2050,24 @@
 outdir, 
-id+%22.exec%22
+execFile
 );%0A%09%09Fil
@@ -2500,25 +2500,26 @@
 dir+%22/%22+
-id+%22.exec
+execFile+%22
 ,dumpone

fix bug add tacoco.exec option