/*****************************************************
 Amino Acid Preference Toolkit in Java
 Pathogen Project
 Department of Computer Science and Engineering
 University of South Carolina
 Columbia, SC 29208
 Contact Email: rose@cse.sc.edu
*****************************************************/

import java.io.*;
import java.util.*;

public class TriplePreferenceMultiSegment
{
  
    public static void main(String[] args)
    {
	//args[0] = fasta filename
	//args[1] = gene filename
	//args[2] = output filename

	try
	    {
		TriplePreferenceMultiSegment ntpms = new TriplePreferenceMultiSegment(args[0], args[1], args[2]);
	    }
	catch (Exception exception)
	    {
		exception.printStackTrace();
	    }
    }

    public TriplePreferenceMultiSegment(String fastaFileName, String geneFileName, String outputFileName) throws Exception
    {
	Hashtable codonToAminoAcidMap = new Hashtable();
	codonToAminoAcidMap.put("CGA", "R");
	codonToAminoAcidMap.put("CGC", "R");
	codonToAminoAcidMap.put("CGG", "R");
	codonToAminoAcidMap.put("CGT", "R");
	codonToAminoAcidMap.put("AGA", "R");
	codonToAminoAcidMap.put("AGG", "R");
	codonToAminoAcidMap.put("CTA", "L");
	codonToAminoAcidMap.put("CTC", "L");
	codonToAminoAcidMap.put("CTG", "L");
	codonToAminoAcidMap.put("CTT", "L");
	codonToAminoAcidMap.put("TTA", "L");
	codonToAminoAcidMap.put("TTG", "L");
	codonToAminoAcidMap.put("TCA", "S");
	codonToAminoAcidMap.put("TCC", "S");
	codonToAminoAcidMap.put("TCG", "S");
	codonToAminoAcidMap.put("TCT", "S");
	codonToAminoAcidMap.put("AGC", "S");
	codonToAminoAcidMap.put("AGT", "S");
	codonToAminoAcidMap.put("ACA", "T");
	codonToAminoAcidMap.put("ACC", "T");
	codonToAminoAcidMap.put("ACG", "T");
	codonToAminoAcidMap.put("ACT", "T");
	codonToAminoAcidMap.put("CCA", "P");
	codonToAminoAcidMap.put("CCC", "P");
	codonToAminoAcidMap.put("CCG", "P");
	codonToAminoAcidMap.put("CCT", "P");
	codonToAminoAcidMap.put("GCA", "A");
	codonToAminoAcidMap.put("GCC", "A");
	codonToAminoAcidMap.put("GCG", "A");
	codonToAminoAcidMap.put("GCT", "A");
	codonToAminoAcidMap.put("GGA", "G");
	codonToAminoAcidMap.put("GGC", "G");
	codonToAminoAcidMap.put("GGG", "G");
	codonToAminoAcidMap.put("GGT", "G");
	codonToAminoAcidMap.put("GTA", "V");
	codonToAminoAcidMap.put("GTC", "V");
	codonToAminoAcidMap.put("GTG", "V");
	codonToAminoAcidMap.put("GTT", "V");
	codonToAminoAcidMap.put("AAA", "K");
	codonToAminoAcidMap.put("AAG", "K");
	codonToAminoAcidMap.put("AAC", "N");
	codonToAminoAcidMap.put("AAT", "N");
	codonToAminoAcidMap.put("CAA", "Q");
	codonToAminoAcidMap.put("CAG", "Q");
	codonToAminoAcidMap.put("CAC", "H");
	codonToAminoAcidMap.put("CAT", "H");
	codonToAminoAcidMap.put("GAA", "E");
	codonToAminoAcidMap.put("GAG", "E");
	codonToAminoAcidMap.put("GAC", "D");
	codonToAminoAcidMap.put("GAT", "D");
	codonToAminoAcidMap.put("TAC", "Y"); 
	codonToAminoAcidMap.put("TAT", "Y"); 
	codonToAminoAcidMap.put("TGC", "C"); 
	codonToAminoAcidMap.put("TGT", "C"); 
	codonToAminoAcidMap.put("TTC", "F");
	codonToAminoAcidMap.put("TTT", "F");
	codonToAminoAcidMap.put("ATA", "I");
	codonToAminoAcidMap.put("ATC", "I");
	codonToAminoAcidMap.put("ATT", "I"); 
	codonToAminoAcidMap.put("ATG", "M"); 
	codonToAminoAcidMap.put("TGG", "W"); 
	codonToAminoAcidMap.put("TAA", "Z"); 
	codonToAminoAcidMap.put("TAG", "Z");
	codonToAminoAcidMap.put("TGA", "Z");

	Hashtable aminoToIndexMap = new Hashtable();
	aminoToIndexMap.put("A", new Integer(0));
	aminoToIndexMap.put("C", new Integer(1));
	aminoToIndexMap.put("D", new Integer(2));
	aminoToIndexMap.put("E", new Integer(3));
	aminoToIndexMap.put("F", new Integer(4));
	aminoToIndexMap.put("G", new Integer(5));
	aminoToIndexMap.put("H", new Integer(6));
	aminoToIndexMap.put("I", new Integer(7));
	aminoToIndexMap.put("K", new Integer(8));
	aminoToIndexMap.put("L", new Integer(9));
	aminoToIndexMap.put("M", new Integer(10));
	aminoToIndexMap.put("N", new Integer(11));
	aminoToIndexMap.put("P", new Integer(12));
	aminoToIndexMap.put("Q", new Integer(13));
	aminoToIndexMap.put("R", new Integer(14));
	aminoToIndexMap.put("S", new Integer(15));
	aminoToIndexMap.put("T", new Integer(16));
	aminoToIndexMap.put("V", new Integer(17));
	aminoToIndexMap.put("W", new Integer(18));
	aminoToIndexMap.put("Y", new Integer(19));
	aminoToIndexMap.put("Z", new Integer(20));

	SequenceReader sequenceReader = new SequenceReader();
	SequenceUtilities sequenceUtilities = new SequenceUtilities();
	
	
	double[] triplePreferenceArray = new double[8000];
	for (int i = 0; i < 8000; i++)
	    {
		triplePreferenceArray[i] = 0;
	    }
	double sum = 0;

	AminoAcidTriplePreference aminoAcidTriplePreference = new AminoAcidTriplePreference();
	
	// go through genes, make full genes when necessary, call
	// triple preference function to generate individual gene preference
	// sum for total

	// since this if for multi-segmented genomes, go through all segments
	System.out.println("Reading multisegment file: " + fastaFileName);
	BufferedReader segmentFastaReader = new BufferedReader(new FileReader(fastaFileName));
	BufferedReader segmentGeneReader = new BufferedReader(new FileReader(geneFileName));
	
	String fastaLine, geneLine;

	while ((fastaLine = segmentFastaReader.readLine()) != null)
	    {
		geneLine = segmentGeneReader.readLine();
		System.out.println("Working on segment: Fasta File => " + fastaLine + " Gene File => " + geneLine);


		char[] sequence = sequenceReader.parseFastaFile(fastaLine).toCharArray();
		char[] complementSequence = sequenceUtilities.complementSequence(sequence);
		int sequenceLength = sequence.length;

		ExtractGenes extractGenesObject = new ExtractGenes(geneLine);		
		int[][] geneIndex = extractGenesObject.getGeneArray();
		int numberOfGenes = extractGenesObject.getNumberOfGenes();

		int geneCount = 0;
		StringBuffer currentCodonSequenceBuffer = new StringBuffer();
		while (geneCount < numberOfGenes)
		    {
		
		
			int geneStart = geneIndex[geneCount][0];
			int geneStop = geneIndex[geneCount][1];
			int geneStrand = geneIndex[geneCount][2];
			int geneContinues = geneIndex[geneCount][3];
			//System.out.println("Start: " + geneStart + " Stop: " + geneStop + " Strand: " + geneStrand + " Continues: " + geneContinues);
		
			int geneLength = (geneStop - geneStart + 1);
		
			if (geneStrand == 0)
			    {
				if (geneStart > 0)
				    {
					for (int i = (geneStart - 1); i < geneStop; i++)
					    {
						currentCodonSequenceBuffer.append(sequence[i]);
					    }
				    }
				else
				    {
					for (int i = sequenceLength + geneStart; i < sequenceLength; i++) //the part of the gene that is at the end of the genome
					    {
						currentCodonSequenceBuffer.append(sequence[i]);
					    }
					for (int i = 0; i < geneStop; i++) // the part of the gene that is at the beginning of the genome
					    {
						currentCodonSequenceBuffer.append(sequence[i]);
					    }
				    }
			    }
			else // complement strand
			    {
				if (geneStart > 0)
				    {
				// take from reverse complement
					StringBuffer newSequenceBuffer = new StringBuffer();
					for (int i = (geneStop -1); i >= (geneStart - 1); i--)
					    {
						// stick the new code in the front if in continues
						newSequenceBuffer.append(complementSequence[i]);	
					    }
					if (currentCodonSequenceBuffer.length() > 0) // continues
					    currentCodonSequenceBuffer.insert(0,newSequenceBuffer.toString());
					else currentCodonSequenceBuffer = newSequenceBuffer;
				    }
				else
				    {
					System.out.println("This case should never occur!");
				    }
			    }

			if (geneContinues == 1) // we are not continuing, so compute aminos
			    {
				char[] codonSequence = currentCodonSequenceBuffer.toString().toCharArray();
				//System.out.println("Current codon sequence: " + new String(codonSequence));
				char[] aminoAcidSequence = sequenceUtilities.translateToAminoAcidSequence(codonSequence, 0, codonSequence.length - 1);
				//System.out.println("AminoAcid Sequence: " + new String(aminoAcidSequence));
			
				double[] triplePreferenceForGene = aminoAcidTriplePreference.calculateTriplePreferenceVectorNoNormalization(aminoAcidSequence);

				for (int i = 0; i < 8000; i++)
				    {
					triplePreferenceArray[i] = triplePreferenceArray[i] + triplePreferenceForGene[i];
					sum = sum + triplePreferenceForGene[i];
				    }
				currentCodonSequenceBuffer.delete(0,currentCodonSequenceBuffer.length());
			    } // gene doesn't continue
			geneCount = geneCount + 1;
		    }
	    } // for each segment in multisegment

	// normalize and output triple preference vector
	for (int i =0 ;i < 8000; i++)
	    {
		triplePreferenceArray[i] = triplePreferenceArray[i] / sum;
	    }

	PrintWriter outputWriter = new PrintWriter(new FileWriter(outputFileName));
	for (int i = 0; i < 8000; i++)
	    {
		if (i == 7999) outputWriter.println(triplePreferenceArray[i]);
		else outputWriter.print(triplePreferenceArray[i] + " ");
		    
	    }
	outputWriter.flush();
	outputWriter.close();
    }


    
}
