package geneFinder;

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

/**
 * class to read in the command line parameters and get all information
 * Copyright (c) 2013,
 * Franziska Zickmann, 
 * ZickmannF@rki.de, Robert Koch-Institute, Berlin, Germany
 * Distributed under the GNU Lesser General Public License, version 3.0
 *
 */

public class ReadInParameters_GeneFinder {
	
	/*
	 * do the read in
	 */
	
	public static void readIn_GF(String[] args){

		if(args.length == 0 || args[0].equals("-h") || args[0].equals("--help") || args[0].equals("-help")){
			printHelp_GF();
		}
		
		String parameter = Arrays.toString(args);
		
		// read in everything:
		
		String inputText = "";
		System.out.println();
		inputText += "Input:\n";
		
		boolean foundGenome = false;
		boolean foundRna = false;
		boolean foundThreadNumber = false;
		boolean foundOutFileName = false;
		boolean foundTool = false;
		boolean foundLength = false;
		boolean havePathOut = false;
		boolean foundMinCov = false;
		boolean foundMaxCov = false;
		boolean foundEndCov = false;
		boolean foundMaxRepHits = false;
		boolean foundHelpPath = false;
		boolean foundIntronMin = false;
		boolean foundAmbiOpti = false;
		boolean foundOptiMethod = false;
		boolean foundDispCov = false;
		boolean foundSolveOn = false;
		boolean foundIter = false;
		boolean foundnoSplLim = false;
		boolean foundSam = false;
		boolean foundSplitIndicator = false;
		boolean foundSecondIndicator = false;
		boolean foundProkaryote = false;
		boolean foundSequential = false;
		boolean foundInprogea = false;
		boolean foundAlternativeCodons = false;
		
		
		if(!parameter.isEmpty() && args.length > 0){
			System.out.println();
			for(int i = 0; i<args.length;i++){
				String arg = args[i];
				
				if(arg.equals("-iG")){  //genome
					
					GeneFinder.pathToGenomeFiles = args[i+1];
					
					if(args[i+1].endsWith(".fasta") || args[i+1].endsWith(".fa")){
						File dir = new File(args[i+1]);
						String[] nameSplit = args[i+1].split("/");
						String name = nameSplit[nameSplit.length-1];
						GeneFinder.pathToGenomeFiles = args[i+1].substring(0,(args[i+1].length()-name.length()));
						foundGenome = true;

						inputText += "genome: \n";

						inputText += " - " + name + "\n";
						GeneFinder.genomeFilesWithNames.put(dir,name);

					}else{
						File dir = new File(args[i+1]);
						String[] fileList = dir.list(new FilenameFilter() {
							public boolean accept(File d, String name) {
								if(name.endsWith(".fasta") || name.endsWith(".fa")){
									return true;
								}else{
									return false;
								}
							}
						});
						if(fileList.length != 0){
							foundGenome = true;
						}
						inputText += "genomes: \n";
						for(String name : fileList){
							inputText += " - " + name + "\n";
							File newFile = new File(args[i+1]+name);
							GeneFinder.genomeFilesWithNames.put(newFile,name);
						}
					}
				} else if(arg.equals("-iR")){ //rna reads
					
					String pathToRnaFiles = args[i+1];
					
					if(pathToRnaFiles.endsWith(".fastq") || pathToRnaFiles.endsWith(".fq")){
						File dir = new File(pathToRnaFiles);
						String[] nameSplit = pathToRnaFiles.split("/");
						String name = nameSplit[nameSplit.length-1];
						foundRna = true;

						inputText += "rna file: \n";

						inputText += " - " + name + "\n";
						GeneFinder.rnaFilesWithNames.put(dir,pathToRnaFiles);

					}else{
						File dir = new File(pathToRnaFiles);
						String[] fileList = dir.list(new FilenameFilter() {
						    public boolean accept(File d, String name) {
						    	if(name.endsWith(".fastq") || name.endsWith(".fq")){
						    		return true;
						    	}else{
						    		return false;
						    	}
						    }
						});
						if(fileList.length != 0){
							foundRna = true;
						}
						inputText += "rna files: \n";
						for(String name : fileList){
							inputText += " - " + name + "\n";
							File newFile = new File(pathToRnaFiles+name);
							GeneFinder.rnaFilesWithNames.put(newFile,pathToRnaFiles+name);
						}
					}
	
				} else if(arg.equals("-outName")){  // output file name

					GeneFinder.outputName = args[i+1];
					inputText += "Outfile name: " + args[i+1] + "\n";
					foundOutFileName = true;

				}else if(arg.equals("-rL")){ // read length

					GeneFinder.readLength = Integer.parseInt(args[i+1]);
					foundLength = true;
					inputText += "Read length: " + GeneFinder.readLength +"\n";
					
				} else if(arg.equals("-mT")){  // read mapper
					String mapper = args[i+1];
					foundTool = true;
					if(mapper.equals("bwa")){
						GeneFinder.useTopHat = false;
						GeneFinder.useBWAsw = false;
					}else if(mapper.equals("bwasw")){
						GeneFinder.useTopHat = false;
						GeneFinder.useBWAsw = true;
					}else{
						GeneFinder.useTopHat = true;
					}
					
				} else if(arg.equals("-minCov")){  // minimal number of required coverage for the beginning of a gene
					GeneFinder.minCoverage = Double.parseDouble(args[i+1]);
					foundMinCov = true;
					inputText += "Minimal required coverage: " + GeneFinder.minCoverage + "\n";
				
				} else if(arg.equals("-maxCov")){  // minimal number of required coverage for the beginning of a gene
					GeneFinder.maxCov = Double.parseDouble(args[i+1]);
					foundMaxCov = true;
					inputText += "Maximal coverage threshold: " + GeneFinder.maxCov + "\n";				
				} else if(arg.equals("-endCov")){  // minimal number of required coverage for the end of a gene
					double endCov = Double.parseDouble(args[i+1]);
					foundEndCov = true;
					if(endCov == -1){
						GeneFinder.endCoverage = -1;  // indicates that it will be reassigned once we obtained the minimum coverage
					}else if(endCov == 0){
						GeneFinder.endCoverage = 0.0; 
					} else{
						GeneFinder.endCoverage = endCov - 0.001;  // subtract 0.001 to make sure that simple greater than is possible in extraction (necessary for endCov == 0)
					}
					
					inputText += "Minimal required end coverage: " + GeneFinder.endCoverage + "\n";
				
				} else if(arg.equals("-settingMapper")){ // setting for topHat
					GeneFinder.settingMapper = args[i+1].substring(1,(args[i+1].length()-1));
					inputText += "Setting of alignment tool: " + GeneFinder.settingMapper + "\n";
				
				} else if(arg.equals("-nT")){  // number of threads allowed to be used
					GeneFinder.numberThreads = Integer.parseInt(args[i+1]);
					foundThreadNumber = true;
					inputText += "Number of threads used in parallel: " + GeneFinder.numberThreads + "\n";
				
				} else if(arg.equals("-out")){  // output directory
					GeneFinder.pathOut = args[i+1];
					havePathOut = true;
					inputText += "Path to output: " + GeneFinder.pathOut + "\n";
				
				} else if(arg.equals("-samForSequential")){  // output directory
					GeneFinder.haveSam_ChromSorted = args[i+1];
					GeneFinder.useSequential = true;
					foundSequential = true;
					inputText += "Perform sequential analysis. Using sam file: " + GeneFinder.haveSam_ChromSorted + "\n";
				
				} else if(arg.equals("-haveSam")){  // output directory
					GeneFinder.haveSam = args[i+1];
					foundSam = true;
					inputText += "Using sam file: " + GeneFinder.haveSam + "\n";
				
				} else if(arg.equals("-scripts")){ // help file directory
					GeneFinder.pathToHelpFiles = args[i+1];
					foundHelpPath = true;
					inputText += "Path to help files: " + GeneFinder.pathToHelpFiles + "\n";
				
				} else if(arg.equals("-maxReportedHitsBWA")){  // max reported hits in BWA output
					GeneFinder.maxReportedHitsBWA = Integer.parseInt(args[i+1]);
					foundMaxRepHits = true;
					inputText += "maximal number of reported hits for BWA: " + GeneFinder.maxReportedHitsBWA + "\n";
				
				} else if(arg.equals("-interval")){  // minimal intron length
					GeneFinder.interval = Integer.parseInt(args[i+1]);
					foundIntronMin = true;
					if(GeneFinder.interval == -1){
						inputText += "use read length as minimal interval length\n";
					}else{
						inputText += "minimal interval length: " + GeneFinder.interval + "\n";	
					}
						
				} else if(arg.equals("-altCodon")){  // alternative start and stop codons
					String pathToAlternative = args[i+1];
					readInAlternativeStartsStops(pathToAlternative);
					foundAlternativeCodons = true;
					inputText += "Alternative Starts and stops provided \n";
				
				} else if(arg.equals("-noAmbiOpti")){  // turn on or off the optimization of ambiguous reads
					foundAmbiOpti = true;			
					GeneFinder.noAmbiOpti = true;
					inputText += "Ambiguous reads are excluded from analysis.\n";	
				} else if(arg.equals("-opti")){
					String optimizer = args[i+1];
					foundOptiMethod = true;
					if(optimizer.equals("glpk")){
						GeneFinder.useCPLEX = false;
						GeneFinder.useGLPK = true;
						inputText += "Using glpk for ambiguous read optimization.\n";
					} else{
						GeneFinder.useCPLEX = true;
						GeneFinder.useGLPK = false;
						inputText += "Using cplex for ambiguous read optimization.\n";
					}
				} else if(arg.equals("-mem")){
					GeneFinder.memForCplex = Integer.parseInt(args[i+1]);			
				} else if(arg.equals("-dispCov")){
					foundDispCov = true;
					int display = Integer.parseInt(args[i+1]);
					if(display == 1){
						GeneFinder.dispCov = true;
					} else{
						GeneFinder.dispCov = false;
					}
				} else if(arg.equals("-solverOn")){
					foundSolveOn = true;
					
					if(args[i+1].equals("y")){
						GeneFinder.optiSolve = true;
					} else{
						GeneFinder.optiSolve = false;
					}
				} else if(arg.equals("-splitRunAndOpti")){
					foundSplitIndicator = true;
			
					if(args[i+1].equals("y")){
						GeneFinder.splitRunAndOpti = true;
					} else{
						GeneFinder.splitRunAndOpti = false;
					}
				} else if(arg.equals("-secondPart")){
					foundSecondIndicator = true;
			
					if(args[i+1].equals("y")){
						GeneFinder.secondPart = true;
					} else{
						GeneFinder.secondPart = false;
					}
				} else if(arg.equals("-prokaryote")){
					foundProkaryote = true;
					GeneFinder.isProkaryote = true;
					/*if(args[i+1].equals("y")){
						GeneFinder.isProkaryote = true;
					} else{
						GeneFinder.isProkaryote = false;
					}*/
				} else if(arg.equals("-iter")){
					foundIter = true;
					int iteration = Integer.parseInt(args[i+1]);
					if(iteration == 1){
						GeneFinder.iteration = 1;
					} else{
						GeneFinder.iteration = 2;
					}
				} else if(arg.equals("-splLim")){
					foundnoSplLim = true;
					double num = Double.parseDouble(args[i+1]);
					if(num == 0){
						GeneFinder.spliceLim = 0.0;
						inputText += "Accept all present splice sites. \n";
					} else if(num == -1){
						GeneFinder.spliceLim = -1.0;				
						inputText += "Using minimal coverage as a threshold for splice site acceptance. \n";
					} else{
						GeneFinder.spliceLim = num;				
						inputText += "Using " + num + " as a threshold for splice site acceptance. \n";
					}
				} else if(arg.equals("-inprogea")){
					foundInprogea = true;
					GeneFinder.inprogeaCall = true;
				}
				
			}
		}

		// defaults and error messages:
		
		if(!havePathOut){
			GeneFinder.pathOut = "";
		}else{
			// check if directory exists, if not, create it
			File f = new File(GeneFinder.pathOut);
			if(!f.exists()){
				Runtime rtAlign = Runtime.getRuntime();
				try {
					String exe = "mkdir " + GeneFinder.pathOut;
					Process pc = rtAlign.exec(exe);
					pc.waitFor();			
				} catch (IOException e) {
					e.printStackTrace();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		if(!foundGenome){
			System.out.println("No genome file specified. Use \"-h\" to print usage options. ");
			System.exit(0);
		}
		if(!foundRna){
			if(!foundSam){
				System.out.println("No rna file specified. Use \"-h\" to print usage options. ");
				System.exit(0);
			}			
		}		
		if(!foundThreadNumber){
			GeneFinder.numberThreads = 1;
		}
		if(!foundTool){
			GeneFinder.useTopHat = true;
		}
		if(!foundMinCov){
			GeneFinder.minCoverage = -1;
			inputText += "Estimate minimal coverage from the alignment. \n";
		}
		if(!foundMaxCov){
			GeneFinder.maxCov = -1;
		}
		if(!foundEndCov){
			GeneFinder.endCoverage = -1;
		}
		if(!GeneFinder.useTopHat && !foundMaxRepHits){
			GeneFinder.maxReportedHitsBWA = 2;
		}
		if(!foundHelpPath){
			//GeneFinder.pathToHelpFiles ="";
			String path = GeneFinder.class.getProtectionDomain().getCodeSource().getLocation().getPath();
			
			try {
				String decodedPath = URLDecoder.decode(path, "UTF-8");
				String scriptPath = decodedPath.substring(0,decodedPath.length()-9);
				GeneFinder.pathToHelpFiles = scriptPath + "scripts/";
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		if(!foundLength){
			GeneFinder.readLength = -1;
		}	
		if(!foundIntronMin){
			GeneFinder.interval = -1;
		}
		if(!foundOutFileName){
			GeneFinder.outputName = "genes";
		}		
		if(!foundAmbiOpti){
			GeneFinder.noAmbiOpti = false;
		}
		if(!foundOptiMethod){
			GeneFinder.useCPLEX = true;
		}
		if(!foundSolveOn){
			GeneFinder.optiSolve = true;
		}
		if(!foundDispCov){
			GeneFinder.dispCov = false;
		}
		if(!foundIter){
			GeneFinder.iteration = 1;
		}
		if(!foundnoSplLim){
			GeneFinder.spliceLim = -1;
			inputText += "Using minimal coverage as a threshold for splice site acceptance. \n";
		}
		if(!foundSam){
			GeneFinder.haveSam = null;
		}
		if(!foundSplitIndicator){
			GeneFinder.splitRunAndOpti = false;
		}
		if(!foundSecondIndicator){
			GeneFinder.secondPart = false;
		}
		if(!foundProkaryote){
			GeneFinder.isProkaryote = false;
		}
		if(!foundSequential){
			GeneFinder.useSequential = false;
		}
		if(!foundInprogea){
			GeneFinder.inprogeaCall = false;
		}
		
		
		GeneFinder.logFile = new File(GeneFinder.pathOut+"log_it" + GeneFinder.iteration + ".txt");
		if(!GeneFinder.secondPart){
			System.out.println(inputText);
			WriteOutput.writeToLogFile(inputText);
		}
		
		/*Runtime rtAlign = Runtime.getRuntime();
		Process firstExe;
		try {
			//String exe = "mkdir "+GeneFinder.pathOut+"resultsRun";
			GeneFinder.logFile = new File(GeneFinder.pathOut+"log_it" + GeneFinder.iteration + ".txt");
			//firstExe = rtAlign.exec(exe);
			//firstExe.waitFor();
			
			if(!GeneFinder.secondPart){
				System.out.println(inputText);
				WriteOutput.writeToLogFile(inputText);
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}*/

	}	
	
	/*
	 * reads in the alternative start and stop codons from a given input file
	 * one line per codon type, with codons tab separated
	 */
	
	public static void readInAlternativeStartsStops(String altFile) {
		
		Map<String,String[]> altCodons = new HashMap<String,String[]>();
			
		try {
			
			BufferedReader br = new BufferedReader(new FileReader(altFile));
			
			String line = "";
			
			while((line = br.readLine()) != null){
				
				String[] lineArr = line.split("\t");
				String[] temp = new String[lineArr.length-1];
				
				if(line.startsWith("START FO")){

					for(int i = 1; i<lineArr.length;++i){
						temp[i-1] = lineArr[i];
					}
					
					altCodons.put("START FO",temp);
				}
				if(line.startsWith("START RE")){
					for(int i = 1; i<lineArr.length;++i){
						temp[i-1] = lineArr[i];
					}
					
					altCodons.put("STOP RE",temp);	// for GIIRA start and stops are switched for the reverse direction
				}
				if(line.startsWith("STOP FO")){
					for(int i = 1; i<lineArr.length;++i){
						temp[i-1] = lineArr[i];
					}
					
					altCodons.put("STOP FO",temp);
				}
				if(line.startsWith("STOP RE")){
					for(int i = 1; i<lineArr.length;++i){
						temp[i-1] = lineArr[i];
					}
					
					altCodons.put("START RE",temp);	// for GIIRA start and stops are switched for the reverse direction
				}
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		GeneFinder.alternativeCodons = altCodons;
	}
	
	/*
	 * print the help text to screen
	 */
	
	public static void printHelp_GF(){
		
		System.out.println();
		System.out.println("GIIRA (Gene Identification Incorporating RNA-Seq data and Ambiguous reads) is a method to identify potential gene regions in a genome " +
				"based on a RNA-Seq mapping and incorporating ambiguously mapped reads.");
		System.out.println();
		System.out.println("Copyright (c) 2013,");
		System.out.println("Franziska Zickmann, ZickmannF@rki.de, Robert Koch-Institute, Berlin, Germany,");	
		System.out.println("Distributed under the GNU Lesser General Public License, version 3.0.");
		System.out.println();
		System.out.println("usage example: \n  java -jar GIIRA.jar -iG genomeFile.fasta -iR rnaFile.fastq -libPath [PATH_CPLEX_LIB] -cp [PATH_CPLEX/cplex.jar] \n");
		System.out.println();
		System.out.println("options: \n  -h : help text and exit \n" +
				" \n -iG [pathToGenomes] : specify path to directory with genome files in fasta format \n" +
				" \n -iR [pathToRna] : specify path to directory with rna read files in fastq format \n" +
				" \n -scripts [absolutePath] : specify the absolute path to the directory containing the required helper scripts, DEFAULT: directory of GIIRA.jar \n" +
				" \n -out [pathToResults] : specify the absolute pyth to the directory that shall contain the results files \n" +
				" \n -outName [outputName] : specify desired name for output files, DEFAULT: genes \n" +
				" \n -haveSam [samfileName]: if a sam file already exists, provide the name, else a mapping is performed. NOTE: the sam file has to be sorted according to read names! \n" +
				" \n -nT [numberThreads] : specify the maximal number of threads that are allowed to be used, DEFAULT: 1 \n" +
				" \n -mT [tophat/bwa/bwasw] : specify desired tool for the read mapping, DEFAULT: tophat \n" +
				" \n -opti [cplex/glpk] : specify the desired optimization method, either using CPLEX optimizer (cplex, DEFAULT) or glpk solver (glpk) \n" +
				" \n -libPath [PATH] : if cplex is the desired optimizer, specify the absolute path to the cplex library Djava.library.path \n" +
				" \n -cp [PATH] : if cplex is the desired optimizer, specify the absolute path to the cplex jar file cplex.jar\n" +
				//" \n -splitRunAndOpti [y/n] : indicates if the optimization and giira shall be run separately, to reduce the memory consumption (y), DEFAULT: n" +
				" \n -mem [int] : specify the amount of memory that cplex is allowed to use \n" +
				" \n -maxReportedHits [int] : if using BWA as mapping tool, specify the maximal number of reported hits, DEFAULT: 2 \n" +
				" \n -prokaryote : if specified, genome is treated as prokaryotic, no spliced reads are accepted, and structural genes are resolved. DEFAULT: False \n" +
				" \n -minCov [double] : specify the minimum required coverage of the gene candidate extraction, DEFAULT: -1 (is estimated from mapping) \n" +
				" \n -maxCov [double] : optional maximal coverage threshold, can also be estimated from mapping (DEFAULT) \n" +
				" \n -endCov [double] : if the coverage falls below this value, the currently open candidate gene is closed. This value can be estimated from the minimum coverage (-1); DEFAULT: -1 \n" +
				" \n -dispCov [0/1] : estimate (1) the coverage histogram for the read mapping, DEFAULT: 0 \n" +
				" \n -interval [int] : specify the minimal size of an interval between near candidate genes, if \"-1\" it equals the read length. DEFAULT: -1 \n " +
				" \n -splLim [double] : specify the minimal coverage that is required to accept a splice site, if (-1) the threshold is equal to minCov, DEFAULT: -1 \n" +
				" \n -rL [int] : specify read length, otherwise this information is extracted from SAM file (DEFAULT) \n" +
				" \n -altCodon [pathToAlternativeCodons] : specify path to txt file with alternative start and stop codons, see example file in scripts folder \n" +
				" \n -samForSequential [pathToSamFile] : if it is desired to analyse chromosomes in a sequential manner, provide a chromosome sorted sam file in addition to the one sorted by read names, DEFAULT: noSequential \n" +
				" \n -noAmbiOpti : if specified, ambiguous hits are not included in the analysis \n" +					
				" \n -settingMapper [(list of parameters)] : A comma-separated list of the desired parameters for TopHat or BWA. Please provide \n" +
				" 	for each parameter a pair of indicator and value, separated by an equality sign. \n" +
				"	Note that paramters intended for the 3 different parts (indexing, aln, sam) of BWA have to be separated by a lowercase bar \n " +
				"	Example: -settingMapper [-a=is_-t=5,-N_-n=5]");
		System.exit(0);
		
	}
	
}
