package geneFinder;

/**
 * controls the jar call
 * Copyright (c) 2013,
 * Franziska Zickmann, 
 * ZickmannF@rki.de, Robert Koch-Institute, Berlin, Germany
 * Distributed under the GNU Lesser General Public License, version 3.0
 */

import java.io.*;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.Map;

import types.Contig;

public class Giira {

	public static int iterationNum;
	public static int optiMethod;       // 0 - cplex // 1 - glpk
	public static String libPath;		// library path for cplex optimization
	public static boolean splitRunAndOpti; // indicates if the optimization and giira shall be run separately, to reduce the memory consumption
	public static String classPath;   // the class path provided in the GIIRA call
	
	public static void main(String[] args) {
		
		if(args.length == 0 || args[0].equals("-h") || args[0].equals("--help")){
			ReadInParameters_GeneFinder.printHelp_GF();
		}

		// get memory
		Runtime rtMem = Runtime.getRuntime();
		double maxMemMB = (((rtMem.maxMemory())/1000.0)/1000.0);
		String str = String.valueOf(maxMemMB);
		String[] mem = str.split("\\.");
		//System.out.println("Maximal Memory: " + mem[0] + "MB");
		
		// get path
		String path = Giira.class.getProtectionDomain().getCodeSource().getLocation().getPath();
		
		long timeBef = System.currentTimeMillis();
		
		try {
			String decodedPath = URLDecoder.decode(path, "UTF-8");
			String[] pathArr = decodedPath.split("/");
			int lengthName = pathArr[pathArr.length-1].length();
			String scriptPath = decodedPath.substring(0,decodedPath.length()-lengthName);
			//String scriptPath = decodedPath.substring(0,decodedPath.length()-9);
			//System.out.println("Path of Giira: " + decodedPath);
			
			classPath = "";
			
			parseForGlobalParas(args);

			// get class path
			
			if(classPath.length() == 0){
				classPath = System.getProperty("java.class.path");
			}
			
			//System.out.println("Class Path: " + classPath);
			
			String argString = "";

			for(String part : args){
				argString += part + " ";
			}

			for(int itNum = 1;itNum<=iterationNum;++itNum){

				//System.out.println();
				//System.out.println("Iteration " + itNum);
				//System.out.println();

				if(splitRunAndOpti){
					// perform two runs, with optimization in between

					// run 1

					String sysCall_1 = "java -Xmx"+ mem[0] +"m -cp " + classPath + ":" + decodedPath + " geneFinder.GeneFinder " + argString + "-iter " + itNum + " -solverOn n -splitRunAndOpti n -scripts " + scriptPath + "scripts/";				
					System.out.println("Call part 1:");
					callAndHandleOutput(sysCall_1,true);
					
					// optimization

					String sysCall_Opti = "";
					if(optiMethod == 0){
						sysCall_Opti = "java -Xmx"+ mem[0] +"m -Djava.library.path=" + libPath + " -cp " + classPath + ":" + decodedPath + " geneFinder.GeneFinder " + argString + "-iter " + itNum + " -splitRunAndOpti y -secondPart y -scripts " + scriptPath + "scripts/";		
					}else{
						sysCall_Opti = "java -Xmx"+ mem[0] +"m -cp " + classPath + ":" + decodedPath + " geneFinder.GeneFinder " + argString + "-iter " + itNum + " -splitRunAndOpti y -secondPart y -scripts " + scriptPath + "scripts/";
					}
					
					System.out.println("Optimization: " + sysCall_Opti);
					callAndHandleOutput(sysCall_Opti,true);			

					// run 2
					
					String sysCall_2 = "java -Xmx"+ mem[0] +"m -cp " + classPath + ":" + decodedPath + " geneFinder.GeneFinder " + argString + "-iter " + itNum + " -solverOn n -splitRunAndOpti n -secondPart y -scripts " + scriptPath + "scripts/";
					System.out.println("Call part 2:");
					callAndHandleOutput(sysCall_2,true);
					
				}else{
					
					String sysCall = "";
					
					if(optiMethod == 0){
						sysCall = "java -Xmx"+ mem[0] +"m -Djava.library.path=" + libPath + " -cp " + classPath + ":" + decodedPath + " geneFinder.GeneFinder " + argString + "-iter " + itNum + " -scripts " + scriptPath + "scripts/";
					}else{
						sysCall = "java -Xmx"+ mem[0] +"m -cp " + classPath + ":" + decodedPath + " geneFinder.GeneFinder " + argString + "-iter " + itNum + " -scripts " + scriptPath + "scripts/";
					}
					
					System.out.println("Call: ");
					callAndHandleOutput(sysCall,true);
					
				}


			}
		} catch (IOException e) {
			System.out.println("IO Exception.");
		}
		
		long timeAft = System.currentTimeMillis();	
		System.out.println("Finished GIIRA in " + (double) (timeAft-timeBef)/1000.0 +"s.");
		
	}
	
	/*
	 * extract the global parameters for GIIRA
	 */
	
	public static void parseForGlobalParas(String[] args){

		boolean foundLib = false;
		boolean foundOpti = false;
		boolean foundSplitIndicator = false;
		boolean foundIteration = false;
		boolean foundCPLEX = false;
		
		String parameter = Arrays.toString(args);
		if(!parameter.isEmpty() && args.length > 0){
			System.out.println();
			for(int i = 0; i<args.length;i++){
				String arg = args[i];
				if(arg.equals("-iter")){
					foundIteration = true;
					int iteration = Integer.parseInt(args[i+1]);
					if(iteration == 1){
						iterationNum = 1;
					} else{
						iterationNum = 2;
					}
				}
				if(arg.equals("-libPath")){
					foundLib = true;
					libPath = args[i+1];
				} else if(arg.equals("-opti")){
					foundOpti = true;
					String optimizer = args[i+1];

					if(optimizer.equals("glpk")){
						optiMethod = 1;
					} else{
						optiMethod = 0;
					}
				} else if(arg.equals("-splitRunAndOpti")){
					foundSplitIndicator = true;
			
					if(args[i+1].equals("y")){
						splitRunAndOpti = true;
					} else{
						splitRunAndOpti = false;
					}
				} else if(arg.equals("-cp")){
					foundCPLEX = true;
					classPath = args[i+1];
				} 
			}
			
			if(!foundLib){
				if(!foundOpti || (foundOpti && optiMethod == 0)){
					System.out.println("Cplex is chosen as optimizer, but no Djava.library.path is provided.");
					System.out.println("Either choose glpk as the optimizer (-opti glpk), or specify the Djava.library.path for cplex with -libPath [PATH].");
					System.exit(0);
				}
			}
			if(!foundCPLEX){
				if(!foundOpti || (foundOpti && optiMethod == 0)){
					System.out.println("Cplex is chosen as optimizer, but no path to cplex.jar is provided.");
					System.out.println("Either choose glpk as the optimizer (-opti glpk), or specify the path to both files with -cp PATH_TO_CPLEX/cplex.jar");
					System.exit(0);
				}
			}
			if(!foundSplitIndicator){
				splitRunAndOpti = false;
			}
			if(!foundIteration){
				iterationNum = 1;
			}
			
		}
	}
	
	/*
	 * call GIIRA and handle the output streams
	 */

	public static void callAndHandleOutput(String sysCall,boolean printAll){
		
		try{
			
			System.out.println(sysCall);
			System.out.println();
			
			Runtime run = Runtime.getRuntime();
			Process exe = run.exec(sysCall);
			
			BufferedReader bExe = new BufferedReader(new  InputStreamReader(exe.getInputStream()));
			BufferedReader bErr = new BufferedReader(new  InputStreamReader(exe.getErrorStream()));
			
			String lineExe = "";
			
			while((lineExe = bExe.readLine()) != null){
				if(printAll){
					System.out.println(lineExe);
				}			
			}
			while((lineExe = bErr.readLine()) != null){
				System.out.println(lineExe);
			}
			
			exe.waitFor();
			
			bExe.close();
			bErr.close();
		} catch (InterruptedException e) {
			System.out.println("Interrupted Exception.");
		} catch (IOException e) {
			System.out.println("IO Exception.");
		}
	}
}
