public class GeneUtils
{

    /**
     * Algorithmic Step 1: Transcribes DNA to mRNA in a single backward pass.
     */
    public static String transcribeToMrna(String dna)
    {
		String mrnaResult = "";

        for (int i = dna.length() - 1; i >= 0; i--)
        {
            char nucleotide = dna.charAt(i);
            if (nucleotide == 'A')
            {
                mrnaResult += 'U';
            }
            else if (nucleotide == 'T')
            {
                mrnaResult += 'A';
            }
            else if (nucleotide == 'C')
            {
                mrnaResult += 'G';
            }
            else if (nucleotide == 'G')
            {
                mrnaResult += 'C';
            }
            else
            {
                mrnaResult += nucleotide;
            }
        }
        return mrnaResult;
    }

    /**
     * Algorithmic Step 2: Returns the index of the first 'AUG' start codon.
     * Returns -1 if not found.
     */
    public static int findStartCodonIndex(String mrna)
    {
        if (mrna == null || mrna.length() < 3)
        {
            return -1;
        }
        
        for (int i = 0; i <= mrna.length() - 3; i++)
        {
            if (mrna.charAt(i) == 'A' && 
                mrna.charAt(i + 1) == 'U' && 
                mrna.charAt(i + 2) == 'G')
            {
                return i;
            }
        }
        return -1;
    }

    /**
     * Algorithmic Step 3: Translates mRNA into a peptide chain.
     * Returns null if start index is -1 OR if a STOP codon is never found.
     */
    public static String translateMrna(String mrna, int startIndex)
    {
        if (startIndex == -1)
        {
            return null;
        }
        
        String polypeptideChain = "";
        boolean first = true;
        boolean hitStop = false;

        for (int i = startIndex; i <= mrna.length() - 3; i += 3)
        {
            String codon = mrna.substring(i, i + 3);
            String aminoAcid = mapCodonToAminoAcid(codon);

            if (aminoAcid.equals("STOP"))
            {
                hitStop = true;
                break;
            }

            if (first)
            {
                polypeptideChain += aminoAcid;
                first = false;
            }
            else
            {
                polypeptideChain += "-" + aminoAcid;
            }
        }

        if (!hitStop)
        {
            return null;
        }

        return polypeptideChain;
    }

    // Converts a codon triplet String into its corresponding amino acid
    public static String mapCodonToAminoAcid(String codon)
    {
        if (codon == null || codon.length() != 3)
        {
            return null;
        }
        
        switch (codon)
        {
            case "AUG":
                return "Met";
            
			case "UUU":
            case "UUC":
                return "Phe";
            
			case "UUA":
            case "UUG":
            case "CUU":
            case "CUC":
            case "CUA":
            case "CUG":
                return "Leu";
            
			case "AUU":
            case "AUC":
            case "AUA":
                return "Ile";
            
			case "GUU":
            case "GUC":
            case "GUA":
            case "GUG":
                return "Val";
            
			case "UCU":
            case "UCC":
            case "UCA":
            case "UCG":
            case "AGU":
            case "AGC":
                return "Ser";
            
			case "CCU":
            case "CCC":
            case "CCA":
            case "CCG":
                return "Pro";
            
			case "ACU":
            case "ACC":
            case "ACA":
            case "ACG":
                return "Thr";
            
			case "GCU":
            case "GCC":
            case "GCA":
            case "GCG":
                return "Ala";
            
			case "UAU":
            case "UAC":
                return "Tyr";
            
			case "CAU":
            case "CAC":
                return "His";
            
			case "CAA":
            case "CAG":
                return "Gln";
            
			case "AAU":
            case "AAC":
                return "Asn";
            
			case "AAA":
            case "AAG":
                return "Lys";
            
			case "GAU":
            case "GAC":
                return "Asp";
            
			case "GAA":
            case "GAG":
                return "Glu";
            
			case "UGU":
            case "UGC":
                return "Cys";
            
			case "UGG":
                return "Trp";
            
			case "CGU":
            case "CGC":
            case "CGA":
            case "CGG":
            case "AGA":
            case "AGG":
                return "Arg";
            
			case "GGU":
            case "GGC":
            case "GGA":
            case "GGG":
                return "Gly";
            
			case "UAA":
            case "UAG":
            case "UGA":
                return "STOP";
            
			default:
                return null;
        }
    }
}