/* Copyright (c) 2012,
 * Mathias Kuhring, KuhringM@rki.de, Robert Koch-Institut, Germany, 
 * All rights reserved. For details, please note the license.txt.
 */

package de.rki.ng4.ipig.tools;

import java.util.HashMap;

/**
 * <p>The Translator provides simple dna translators, one for the common dna to peptide translation 
 * and another for a strand to complement strand translation.</p>
 * 
 * @author Mathias Kuhring
 */
public class Translator {

	private HashMap<String,String> codonTable;
	
	/**
	 * The constructor initializes a HashMap for the codon-aminoacid relations with a standard codon table.
	 */
	public Translator(){
		codonTable = new HashMap<String,String>();
		initializeCodonTable();
	}
	
	/**
	 * <p>This method provides a dna to peptide translation with a standard codon table. Peptides are returned in one-letter code.</p>
	 *  
	 *  <p>Note: this method handles only valid codons. A dna string including other characters than ACGT (e.g. N)
	 *  will produce a non-valid codon. This leads to "null" in the peptide and therefore messes the peptide length up.</p>
	 *  
	 *  <p>Note: only dna strings with a length completely divisible by 3 are considered, as a codon has length 3.
	 *  For strings with a impractical length the method returns null.</p>
	 *  
	 * @param dna a dna string
	 * @return a one-letter coded peptide string or null if dna length is impractical
	 */
	public String dnaToPeptide(String dna){
		if (dna.length() % 3 != 0)
			return null;
		
		StringBuffer peptide = new StringBuffer();
		String codon;
		String aa;
		
		dna = dna.toUpperCase();
		for (int i=0; i<dna.length(); i+=3){
			codon = dna.substring(i,i+3);
			aa = codonTable.get(codon);
			peptide.append(aa);
		}
		
		return peptide.toString();
	}
	
	/**
	 * <p>Builds the complement string of a dna string.</p>
	 * 
	 * <p>This includes A->T, C->G, G->C and T->A. Other characters (e.g. U or N) are not supported and will not be changed.</p>
	 * 
	 * <p>Note: the output string is not reversed!</p>
	 * 
	 * @param dna a dna string
	 * @return
	 */
	public static String complement(String dna){
		String tmp = dna.toUpperCase();
		StringBuffer compl = new StringBuffer();

		for (int i=0; i<tmp.length(); i++){
			switch (tmp.charAt(i)){
			case 'A':
				compl.append('T');
				break;
			case 'C':
				compl.append('G');
				break;
			case 'G':
				compl.append('C');
				break;
			case 'T':
				compl.append('A');
				break;
			default:
				compl.append(tmp.charAt(i));
			}
		}

		return compl.toString();
	}
	
	// builds the hashmap for the codon-aminoacid relations
	private void initializeCodonTable(){

		String[] bases = {"T","C","A","G"};

		for(String base1 : bases){
			for(String base2 : bases){
				for(String base3 : bases){

					if(base1.equals("T")){

						if(base2.equals("T")){
							if(base3.equals("T") || base3.equals("C")){
								String codon = base1+base2+base3;
								codonTable.put(codon, "F");
							}else{
								String codon = base1+base2+base3;
								codonTable.put(codon, "L");
							}
						}else if(base2.equals("C")){
							String codon = base1+base2+base3;
							codonTable.put(codon, "S");
						}else if(base2.equals("A")){
							if(base3.equals("T") || base3.equals("C")){
								String codon = base1+base2+base3;
								codonTable.put(codon, "Y");
							}else{
								String codon = base1+base2+base3;
								codonTable.put(codon, "*");
							}
						}else if(base2.equals("G")){
							if(base3.equals("T") || base3.equals("C")){
								String codon = base1+base2+base3;
								codonTable.put(codon, "C");
							}else if(base3.equals("A")){
								String codon = base1+base2+base3;
								codonTable.put(codon, "*");
							}else if(base3.equals("G")){
								String codon = base1+base2+base3;
								codonTable.put(codon, "W");
							}
						}

					}

					if(base1.equals("C")){

						if(base2.equals("T")){
							String codon = base1+base2+base3;
							codonTable.put(codon, "L");
						}else if(base2.equals("C")){
							String codon = base1+base2+base3;
							codonTable.put(codon, "P");
						} else if(base2.equals("A")){
							if(base3.equals("T") || base3.equals("C")){
								String codon = base1+base2+base3;
								codonTable.put(codon, "H");
							}else{
								String codon = base1+base2+base3;
								codonTable.put(codon, "Q");
							}
						} else if(base2.equals("G")){
							String codon = base1+base2+base3;
							codonTable.put(codon, "R");
						}

					}

					if(base1.equals("A")){

						if(base2.equals("T")){
							if(base3.equals("G")){
								String codon = base1+base2+base3;
								codonTable.put(codon, "M");
							}else{
								String codon = base1+base2+base3;
								codonTable.put(codon, "I");
							}
						}else if(base2.equals("C")){
							String codon = base1+base2+base3;
							codonTable.put(codon, "T");
						} else if(base2.equals("A")){
							if(base3.equals("T") || base3.equals("C")){
								String codon = base1+base2+base3;
								codonTable.put(codon, "N");
							}else{
								String codon = base1+base2+base3;
								codonTable.put(codon, "K");
							}
						} else if(base2.equals("G")){
							if(base3.equals("T") || base3.equals("C")){
								String codon = base1+base2+base3;
								codonTable.put(codon, "S");
							}else{
								String codon = base1+base2+base3;
								codonTable.put(codon, "R");
							}
						}

					}

					if(base1.equals("G")){

						if(base2.equals("T")){
							String codon = base1+base2+base3;
							codonTable.put(codon, "V");
						}else if(base2.equals("C")){
							String codon = base1+base2+base3;
							codonTable.put(codon, "A");
						} else if(base2.equals("A")){
							if(base3.equals("T") || base3.equals("C")){
								String codon = base1+base2+base3;
								codonTable.put(codon, "D");
							}else{
								String codon = base1+base2+base3;
								codonTable.put(codon, "E");
							}
						}else if(base2.equals("G")){
							String codon = base1+base2+base3;
							codonTable.put(codon, "G");
						}
					}
				}
			}
		}
	}
}
