package geneFinder;


/**
 * manages gene finding
 * 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.util.HashMap;
import java.util.Map;

import types.*;


public class GeneFinder {

	public static String pathToGenomeFiles; 	// path to directory with genome.fasta
	public static String pathOut;		 		// path to directory for resultsFiles
	public static String pathToHelpFiles;		// path to directory with all help scripts
	
	public static File logFile;					// file to store all run information
	public static String outputName;			// basis name for all output files
	public static String haveSam;				// if a sam file already exists, haveSam contains the name
	
	public static Map<File,String> genomeFilesWithNames = new HashMap<File,String>();
	public static Map<File,String> rnaFilesWithNames = new HashMap<File,String>();

	public static boolean useTopHat;			// indicator for mapping tool
	public static String settingMapper;			// setting for the mapping tool, differs slightly depending on which tool was chosen
	public static int maxReportedHitsBWA;		// specify number of multiple hits maximal reported in tag of BWA
	public static boolean useBWAsw;				// use longer reads and therefore choose BWAsw as mapping tool
	public static boolean useCPLEX;
	public static boolean useGLPK;
	public static int memForCplex = -1;			// if necessary, memory is set by user
	public static boolean optiSolve;			// if we have separate runs to reduce the memory consumption, this parameter turns off the optimization solver
	
	public static int readLength;				// read length of the rna reads
	public static double minCoverage;			// coverage threshold for the beginning of a gene
	public static double endCoverage;			// coverage threshold for the end of a gene
	
	public static double maxCov; // threshold in case average cov and median cov differ too much

	public static int interval;				// minimal interval length
	public static boolean dispCov;				// decide whether the coverage histogram is computed
	public static double spliceLim; 			// coverage threshold for splice site acceptance
	
	public static boolean isProkaryote;         // if set to true, it forbids the extraction of spliced reads
	
	public static boolean noAmbiOpti;			// do not use ambiguous reads and perform no optimization
	public static int numberThreads;			// indicates the maximal number of threads used during the run

	public static Map<String,Contig> mappedContigs = new HashMap<String,Contig>();
	public static Map<Contig,String> contigTOname = new HashMap<Contig,String>();

	public static boolean splitRunAndOpti; // indicates if the optimization and GIIRA shall be run separately, to reduce the memory consumption
	public static int iteration;				// number of iterations
	public static double ambiProportion;
	
	public static boolean secondPart;       // indicates whether we print out messages or not, required to avoid double messaging when in splitted analysis
	public static boolean useSequential;    // indicate if we have a second chrom sorted Sam file which is parsed in a sequential manner
	public static String haveSam_ChromSorted;	// if a sam file already exists, haveSam_ChromSorted contains the name (needed at the moment for sequential stuff)
	
	public static boolean inprogeaCall;   // indicates whether called from inprogea framework or independently
	
	public static void main(String[] args){		
		
		manager(args);
	
	}

	/*
	 * manages the first part
	 */
	
	public static Object[] manager(String[] args){
		
	ReadInParameters_GeneFinder.readIn_GF(args);
		
		/*Gene gene = new Gene();
		gene.startPos = 0;
		String seq = readInFasta();
		Prokaryote_Specials.define_OrfsInOperon(seq,gene);
		System.exit(0);*/
		
		long timeBef = System.currentTimeMillis();

		PrepareMapping_GF mappingPrep = new PrepareMapping_GF();
		String nameRef = mappingPrep.prepareRefFile_GF();

		File inputFileAlign;
		File inputFileAlign2 = null;
		
		if(GeneFinder.useSequential){
			 inputFileAlign2 = new File(haveSam_ChromSorted);
		}

		if(useTopHat){

			if(haveSam != null){
				inputFileAlign = new File(haveSam);
			}else{
				
				inputFileAlign = new File(pathOut+"accepted_hits.sam");
				GeneFinder.haveSam = pathOut+"accepted_hits.sam";
				
				// first test if not already created in earlier rounds
				
				try{
					
					BufferedReader br = new BufferedReader(new FileReader(inputFileAlign));
					br.close();
					
				}catch (IOException e) {
					TopHat_Call tophatStart = new TopHat_Call();
					tophatStart.callTopHat(nameRef);
				}

			}
		}else{

			if(haveSam != null){
				inputFileAlign = new File(haveSam);				
			}else{
				
				inputFileAlign = new File(pathOut+"aln_BWA.sam");
				GeneFinder.haveSam = pathOut+"aln_BWA.sam";
				
				// first test if not already created in earlier rounds
				
				try{
					
					BufferedReader br = new BufferedReader(new FileReader(inputFileAlign));
					br.close();
					
				}catch (IOException e) {
					BWA_Call bwaStart = new BWA_Call();
					bwaStart.callBWA(new File(nameRef+".fasta"), pathOut+"aln_BWA.sam"); 
					
				}
	
			}
		}
		
		if(iteration == 2){
			WriteOutput.sortReassignSamFile();
		}
		
		SamParser parser = new SamParser();
		
		parser.samFileParser(inputFileAlign,inputFileAlign2,nameRef);
		
		if(iteration == 2){
			WriteOutput.removeReassignSamFile();
		}

		geneFinder_managing(nameRef, "");

		long timeAft = System.currentTimeMillis();	
		System.out.println("Gene identification finished in " + (double) (timeAft-timeBef)/1000.0 +"s.");
		WriteOutput.writeToLogFile("Gene identification finished in " + (double) (timeAft-timeBef)/1000.0 +"s.");
		
		if(inprogeaCall){
			return new Object[] {mappedContigs,readLength};
		}else{
			return null;
		}
	}
	
	/*
	 * coordinates everything necessary exclusively for the gene finder
	 */

	public static void geneFinder_managing(String nameRef, String namePartOut){

		long timeBef = System.currentTimeMillis();
		
		if(!isProkaryote){
			ExtractGeneCandidates searchC = new ExtractGeneCandidates();
			searchC.initializeClusterSearch(nameRef);
		}else{			
			ProkaryoteExtraction searchC_Pro = new ProkaryoteExtraction();
			searchC_Pro.initializeClusterSearch(nameRef);
		}

		long timeAft = System.currentTimeMillis();	
		
		if(!GeneFinder.secondPart){
			System.out.println("Time required for candidate extraction: " + (double) (timeAft-timeBef)/1000.0 +"s.\n");
			WriteOutput.writeToLogFile("Time required for candidate extraction: " + (double) (timeAft-timeBef)/1000.0 +"s.\n");
			
		}
		
		if(!GeneFinder.noAmbiOpti){
			if(useCPLEX){
				OptimizeAmbis.maxFlowLP();
			}else{
				OptimizeAmbis_GLPK.maxFlowLP();
			}
					 
		}
			
		double[] minMax = CalculateScores.assignGeneScores(false);
				
		if(isProkaryote){
			WriteOutput.writeGeneFinderOutput_Prokaryote(minMax,namePartOut);
		}else{
			WriteOutput.writeGeneFinderOutput(minMax,namePartOut);
		}
		
	}
	
	public static String readInFasta(){
		
		
		String seq = "";
		
		try {
			BufferedReader br = new BufferedReader(new FileReader(new File("/home/franziska/paper_giira/EcoliSim/testAlign_30_6/extract4.fasta")));

			String line = "";
			
			while((line = br.readLine()) != null){
				if(!line.startsWith(">")){
					seq += line;
				}
			}
		} catch (FileNotFoundException e) {
			
			e.printStackTrace();
		} catch (IOException e) {
			
			e.printStackTrace();
		}
		
		System.out.println(seq);
		return seq;
	}

}
