/**********************************************************************************
 *                        DNA Sequence Translator 1.0.                            *
 *       Copyright (C) 2006  ZIJUAN LIU, YUBO DONG. yubodong@gmail.com            *
 **********************************************************************************
 * This program is free software; you can redistribute it and/or modify           *
 * it under the terms of the GNU General Public License as published by           *
 * the Free Software Foundation; either version 2 of the License, or              *
 * (at your option) any later version.                                            *
 *                                                                                *
 * This program is distributed in the hope that it will be useful,                *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of                 *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                  *
 * GNU General Public License for more details.                                   *
 *                                                                                *
 * You should have received a copy of the GNU General Public License              *
 * along with this program; if not, write to the Free Software                    *
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA     *
 *                                                                                *
 **********************************************************************************/
//---------------------------------------------------------------------------------
//Update History
//---------------------------------------------------------------------------------
//    Date     |    Author    |  Reason
//---------------------------------------------------------------------------------
// 02/25/2006  |   Yubo Dong  | Created the first version of SEQTranslator
//---------------------------------------------------------------------------------
 
//
//Class for DNA Sequence Translator
//
function SEQTranslator(){
   //
   // m_strSEQ stores the after-cleanup DNA sequence.
   // m_strSEQProcessed stores the Amino Acid Code for the after-cleanup DNA sequence
   //
   var m_strSEQ = null,m_strSEQProcessed = null;

   this.process = process;
   this.getResult = getResult;
   this.display = display;
   this.getCodonTable = getCodonTable;
   this.reverseSEQ = reverseSEQ;

   
   //
   // Codon table from http://www.kazusa.or.jp/java/codon_table_java/
   //
   var m_arrMapping = new Array(
	   "ATG","M","Met",	   "ATC","I","Ile",	   "ATA","I","Ile",	   "ATT","I","Ile",	   "ACA","T","THR",	   "ACT","T","Thr",
	   "ACG","T","Thr",	   "ACC","T","Thr",	   "AAT","N","Asn",	   "AAC","N","Asn",	   "AAA","K","Lys",	   "AAG","K","Lys",
	   "AGT","S","Ser",	   "AGC","S","Ser",	   "AGA","R","Arg",	   "AGG","R","Arg",	   "TTT","F","Phe",	   "TTC","F","Phe",
	   "TTA","L","Leu",	   "TTG","L","Leu",	   "TCA","S","Ser",	   "TCT","S","Ser",	   "TCG","S","Ser",	   "TCC","S","Ser",
	   "TAG","*","***",	   "TAA","*","***",	   "TAC","Y","Tyr",	   "TAT","Y","Tyr",	   "TGT","C","Cys",	   "TGC","C","Cys",
	   "TGG","W","Trp",	   "TGA","*","***",	   "GTG","V","Val",	   "GTC","V","Val",	   "GTA","V","Val",	   "GTT","V","Val",
	   "GCA","A","Ala",	   "GCT","A","Ala",	   "GCG","A","Ala",	   "GCC","A","Ala",	   "GAT","D","Asp",	   "GAC","D","Asp",
	   "GAG","E","Glu",	   "GAA","E","Glu",	   "GGA","G","Gly",	   "GGT","G","Gly",	   "GGG","G","Gly",	   "GGC","G","Gly",
	   "CTG","L","Leu",    "CTA","L","Leu",	   "CTT","L","Leu",	   "CTC","L","Leu",	   "CCT","P","Pro",	   "CCA","P","Pro",
	   "CCC","P","Pro",	   "CCG","P","Pro",	   "CAT","H","His",	   "CAC","H","His",	   "CAA","Q","Gln",	   "CAG","Q","Gln",
	   "CGA","R","Arg",	   "CGT","R","Arg",	   "CGG","R","Arg",	   "CGC","R","Arg");

   function getCodonTable(){return m_arrMapping;}

   function process(seq, one_three){
       m_strSEQ = seq;
	   var strProcessedSEQ = seq.toUpperCase();
       strProcessedSEQ = preProcessSEQ(strProcessedSEQ);
	   strProcessedSEQ = processHelper(strProcessedSEQ, one_three);

	   if ( strProcessedSEQ == null ) return null;
	   m_strSEQProcessed = strProcessedSEQ;
	   var obj = postProcess(strProcessedSEQ);
	   return obj;
   }
   function preProcessSEQ(str){
       //Remove all space
	   str = str.replace(/ /g,'');
	   str = str.replace(/\n/g,'');
	   str = str.replace(/\r/g,'');
	   str = str.replace(/\t/g,'');
       
	   //Replace all Us with Ts
	   str = str.replace(/U/g,'T');

	   //Remove all non A,T,G,C character
	   var strExceptional="BDEFHIJKLMNOPQRSUVWXYZ0123456789";
	   for ( var i = 0; i < strExceptional.length; i ++ ){
           eval("str = str.replace(/" + strExceptional.charAt(i) + "/g,'');");
	   }


	   //Remove all special character
	   str = str.replace(/[/]/g,'');
	   str = str.replace(/[\"\']/g,'');
	   str = str.replace(/[.]/g,'');
	   str = str.replace(/[(]/g,'');
	   str = str.replace(/[)]/g,'');
	   str = str.replace(/[_~!`+-=;:\[\]\{\}\|\\@#\$%^&\*,\?<>]/g,'');

	   m_strSEQ = str;
	   return str;
   }
   //
   //Reverse the DNA sequence and turn all As to Ts , all Ts to As, all Cs to Gs and all Gs to Cs
   //
   function reverseSEQ(seq){
       var newSEQ = "";
       for ( var i = seq.length - 1; i >= 0; i -- ){
	       var ch = seq.charAt(i);
		   switch (ch){
		      case 'A': ch = 'T'; break;
		      case 'T': ch = 'A'; break;
		      case 'G': ch = 'C'; break;
		      case 'C': ch = 'G'; break;
			  default: ch = ""; break;
		   }
		   newSEQ += ch;
	   }
	   return newSEQ;
   }

   //
   //Look up codon database for given codon
   //
   function lookupCodon(strCodon){
       var obj = null;
       for ( var i = 0; i < m_arrMapping.length; i += 3 ){
	       if ( strCodon == m_arrMapping[i] ){
		      obj = new Object();
			  obj.one = m_arrMapping[i+1];
			  obj.three = m_arrMapping[i+2];
			  break;
		   }
	   }
	   return obj;
   }

   function processHelper(seq, one_or_three){
       //Looking for ATG
	   var iIndex = seq.indexOf("ATG");

	   //If to ATG was found in original sequence, reverse the original sequence and re-look again.
	   if ( iIndex == -1 ) seq = reverseSEQ(seq);

	   iIndex = seq.indexOf("ATG");
	   if ( iIndex == -1 ){
	      alert("Sorry, unrecognized DNA sequence!");
		  return null;
	   }

	   var newSEQ = "";
	   seq = seq.substr(iIndex, seq.length - iIndex);
	   m_strSEQ = seq;

	   for ( var i = 0; i < seq.length; i += 3 ){
	       var tmpSEQ = seq.substr(i,3);
		   var obj = lookupCodon(tmpSEQ);
		   if ( obj == null ) newSEQ += "   ";
		   else{
		      if ( one_or_three )
			     newSEQ += " " + obj.one + " ";
			  else
			     newSEQ += obj.three;
		   }
	   }
	   return newSEQ;
   }
   function postProcess(strSEQ){
       var strSEQOriginal = "", strSEQProcessed = "";
       for ( var i = 0; i < m_strSEQ.length; i += 3 ){
	       var tmpSEQ = m_strSEQ.substr(i,3);
		   strSEQOriginal += tmpSEQ + " ";
		   tmpSEQ = strSEQ.substr(i,3);
		   strSEQProcessed += tmpSEQ + " ";
	   }
	   var obj = new Object();

	   obj.original = strSEQOriginal;
	   obj.processed = strSEQProcessed;
	   return obj;
   }
   function getResult(){
	   if ( m_strSEQProcessed == null ) return null;
	   var obj = new Object();
	   obj.original = m_strSEQ;
	   obj.processed = m_strSEQProcessed;
	   return obj;
   }
   function padNumber(iNum, len){
       var strNum = iNum + "";
	   var newStr="";
	   for ( var i = 0; i < len - strNum.length; i ++ )
	       newStr += "&nbsp";
	   return newStr + strNum;
   }
   function display(e, obj){
 	   var str = "<div align='center' style='font-family:courier new; font-size:12px; font-weight:700; color:black;'>";
	   str += "SEQTranslator 1.0 All rights reserved. Contact: ziliu@med.wayne.edu";
	   str += "</div><br>";
       var strHTML = str + "<div align='left' style='font-family:courier new; font-size:12px; font-weight:700; color:red;'>";
	   var iNumOriginal = 1, iNumProcessed = 1;
       
	   strHTML += "<span style='color:black;'>";
	   strHTML += padNumber(1, 8) + padNumber(5, 5) + padNumber(10, 8) + padNumber(15, 6) + padNumber(20, 7);
	   strHTML += padNumber(25, 7) + padNumber(30, 6) + padNumber(35, 7) + padNumber(40, 7) + padNumber(45, 6);
	   strHTML += padNumber(50, 7) + padNumber(55, 7) + padNumber(60, 6);
	   strHTML += "</span><br>";

       for ( var i = 0; i < obj.original.length; i += 80 ){
	       var tmpSEQ1 = obj.original.substr(i,80);
	       var tmpSEQ2 = obj.processed.substr(i,80);
		   tmpSEQ1 = "<span style='color:black;'>" + padNumber(iNumOriginal, 5) + ":&nbsp;</span><span style='color:red;'>" + tmpSEQ1.replace(/ /g,"&nbsp;") + "</span>";
		   tmpSEQ2 = "<span style='color:black;'>" + padNumber(iNumProcessed, 5) + ":&nbsp;</span><span style='color:blue;'>" + tmpSEQ2.replace(/ /g,"&nbsp;") + "</span>";
		   strHTML += tmpSEQ1 + "<br>";
		   strHTML += tmpSEQ2 + "<br><br>";
		   iNumOriginal += 60;
		   iNumProcessed += 20;
	   }
	   strHTML += "</div>";
	   e.innerHTML = strHTML;
   }
}

