/*****************************************************
 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 TriplePreference
{
  
    public static void main(String[] args)
    {
	//args[0] = fasta filename
	//args[1] = gene filename
	//args[2] = output filename

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

    public TriplePreference(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();
	char[] sequence = sequenceReader.parseFastaFile(fastaFileName).toCharArray();
	char[] complementSequence = sequenceUtilities.complementSequence(sequence);
	int sequenceLength = sequence.length;

	ExtractGenes extractGenesObject = new ExtractGenes(geneFileName);		
	int[][] geneIndex = extractGenesObject.getGeneArray();
	int numberOfGenes = extractGenesObject.getNumberOfGenes();
	
	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

	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;
	    }

	// 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();
    }


    
}
