import javax.swing.*;
import pal.tree.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.awt.*;
import javax.imageio.*;
import java.awt.event.*;



/**
*An applet that contains a canvas that draws trees!
Ultimately, the purpose of the applet is to contain a <i>PhyloCanvas</i>
*/
public class PhyloApplet extends JApplet
	{

	
	public class WaitFrame extends JFrame implements WindowListener
		{

		Image myImage=null;

		public boolean imageUpdate(Image img,
                    int infoflags,
                    int x,
                    int y,
                    int width,
                    int height)
			{
			repaint();
			return true;
			}


		public void windowActivated(WindowEvent e)
			{
			// Invoked when the Window is set to be the active Window.
			}

		public void windowClosed(WindowEvent e)
			{
			// Invoked when a window has been closed as the result of calling dispose on the window. 
			}

		public void windowDeactivated(WindowEvent e) 
			{
			//Invoked when a Window is no longer the active Window. 
			}

		public void windowDeiconified(WindowEvent e)
			{ 
			//Invoked when a window is changed from a minimized to a normal state. 
			}

		public void windowIconified(WindowEvent e) 
			{
			//Invoked when a window is changed from a normal to a minimized state. 
			}

		public void windowOpened(WindowEvent e)
			{
			//Invoked the first time a window is made visible. 
			}


		public void paint(Graphics g)
			{
			if(myImage!=null)
				{
				g.drawImage(myImage, 0, 0, null);
				}
			}


		public void windowClosing(WindowEvent we)
			{
			show();
			}




		public WaitFrame(String imgFile)
			{
			
			try
				{
				myImage=ImageIO.read(new URL(getCodeBase(),imgFile));
				}
			catch(Exception e)
				{

				}

			//setAlwaysOnTop(true);
			addWindowListener(this);
			setTitle("The Tree Is Being Built....");

			if(myImage!=null)
				{
				setSize(myImage.getWidth(this),myImage.getHeight(this));
				}
			//getContentPane().add(new JLabel("HELLO WORLD!"));
			setVisible(true);
			show();

			}
		}


	/**
	*Given a string, replace all commas, colons, and apostrophes with a string of ZERO length
	*@param s a string to perform the replacements on.
	*@return the string with the replacements done
	*/
	public static String removeApostrophesCommasAndColons(String s)
		{
		s=s.replaceAll(",","");
		s=s.replaceAll(":","");
		s=s.replaceAll("'","");
		return s;
		}


	/**
	*Given a URL, access it and read the contents and return an array of string of the content!
	*@param u a URL to get content from
	*@return an array of Strings of the lines of the content
	*/
	public static String[] readStringFromURL(URL u) throws Exception
		{
		String[] l=null;
		String i=null;
		URLConnection uc=u.openConnection();
		InputStream is=uc.getInputStream();
		InputStreamReader isr=new InputStreamReader(is);
		BufferedReader mbr=new BufferedReader(isr);
		while(mbr.ready())
			{
			i=mbr.readLine();
			while(i.indexOf(" ")!=(-1) && i.indexOf("\t")!=(-1) && i.indexOf("\n")!=(-1))
				{
				i=i.replaceAll(" ","");
				i=i.replaceAll("\t","");
				i=i.replaceAll("\n","");
				}
			l=addLine(i,l);
			}
		mbr.close();
		return l;
		}


	/**
	*Given a string and an array of strings, return TreeUtils.addLine(newLine,existing);
	*@param existing the array to add a string to  (lenght l)
	*@param newLine to String to append to the array
	*@return an array of length l+1 with the original argument but with the newLine appended
	*/
	private static String[] addLine(String newLine,String[] existing)
		{
		return TreeUtils.addLine(newLine,existing);
		/**String[] toBeReturned=null;

		if(existing==null)
			{
			toBeReturned=new String[1];
			toBeReturned[0]=new String(newLine);
			return toBeReturned;
			}
		else if(existing.length==0)
			{
			toBeReturned=new String[1];
			toBeReturned[0]=new String(newLine);
			return toBeReturned;
			}
		else
			{
			toBeReturned=new String[existing.length+1];

			for(int index=0;index<existing.length;index++)
				{
				toBeReturned[index]=new String(existing[index]);
				}
			toBeReturned[existing.length]=new String(newLine);
			return toBeReturned;
			}*/
		}


	/**
	*Given a file name, in the form of a string, read the file contents, concatenting all lines into one, and return the resulting string
	*@param treeFile the file to read
	*@return a String representing the file's contents (all concatenated into one single line)
	*/
	public static String readStringFromFile(String treeFile)
		{
		try
			{
			//open the file and read the stuff....

			BufferedReader mbr=null;
			File myFile=new File(treeFile);
			FileReader mfr=new FileReader(myFile);
			mbr=new BufferedReader(mfr);
			
			String[] l=null;
			String i=null;

			while(mbr.ready())
				{
				i=mbr.readLine();
				while(i.indexOf(" ")!=(-1) && i.indexOf("\t")!=(-1) && i.indexOf("\n")!=(-1))
					{
					i=i.replaceAll(" ","");
					i=i.replaceAll("\t","");
					i=i.replaceAll("\n","");
					}
				l=addLine(i,l);
				}
			mbr.close();
			return i;

			}
		catch(Exception e)
			{
			e.printStackTrace();
			System.exit(0);
			}
		System.exit(0);
		return new String("");
		}



	/*
	private static String[] getFileLinesFromSerialInputAndUser(String serialInput,String additionalSequences) throws Exception
		{
		
		String[] inputSerials=serialInput.split(",");
		
		if(inputSerials==null || inputSerials.length<=0)
			{
			System.out.println("Error - no serials passed!!!!");
			}
		String[] descriptions=new String[inputSerials.length+1];
		for(int dn=0;dn<descriptions.length-1;dn++)
			{
			descriptions[dn]=TreeUtils.getDataGivenSerialFromServer(inputSerials[dn],"collection_description");
			if(descriptions[dn].trim().length()<=0)
				{
				descriptions[dn]=new String("***No description found in record!****");
				}
			descriptions[dn]=new String(""+inputSerials[dn]+" "+descriptions[dn]);
			System.out.println(descriptions[dn]);
			}
		descriptions[descriptions.length-1]=new String("***Outgroup***");

		String[] sequences=new String[inputSerials.length+1];
		for(int dn=0;dn<sequences.length-1;dn++)
			{
			sequences[dn]=TreeUtils.getDataGivenSerialFromServer(inputSerials[dn],"nucleotide_sequence");
			System.out.println("Retrived sequence #"+dn+":");
			System.out.println(sequences[dn]);
			}
		sequences[sequences.length-1]=new String("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");

		String[] additions=null;
		if(additionalSequences.lastIndexOf(",")==(-1))
			{
			System.out.println("Only a single user sequence detected!");
			if(additionalSequences.length()<=1)
				{
				additions=new String[0];
				}
			else
				{
				additions=new String[1];
				additions[0]=new String(additionalSequences);
				}
			}
		else
			{
			System.out.println("Multiple user sequences detected.");
			additions=additionalSequences.split(",");
			}


		String[] userDesc=new String[additions.length];
		for(int ud=0;ud<userDesc.length;ud++)
			{
			userDesc[ud]=new String("Submitted Isolate");
			}

		
		System.out.println("Before additions :");
		System.out.println("Seq len is "+sequences.length+".");
		System.out.println("Des len is "+descriptions.length+".");
		System.out.println("Sequences :"+Arrays.toString(sequences));
		System.out.println("Descriptions :"+Arrays.toString(descriptions));




		if(additions.length>0)
			{
			String[] newDescriptions=new String[additions.length+descriptions.length];
			System.arraycopy(descriptions,0,newDescriptions,0,descriptions.length);
			System.arraycopy(userDesc,0,newDescriptions,descriptions.length,userDesc.length);
			descriptions=newDescriptions;
			String[] newSequences=new String[additions.length+sequences.length];
			System.arraycopy(sequences,0,newSequences,0,sequences.length);
			System.arraycopy(additions,0,newSequences,sequences.length,additions.length);
			sequences=newSequences;
			}


		System.out.println("After additions :");
		System.out.println("Seq len is "+sequences.length+".");
		System.out.println("Des len is "+descriptions.length+".");
		System.out.println("Sequences :"+Arrays.toString(sequences));
		System.out.println("Descriptions :"+Arrays.toString(descriptions));

		double[][] dists=new double[sequences.length][];


		long start=System.currentTimeMillis();
		AlignmentMaster mam=new AlignmentMaster(sequences,descriptions);
		while(!mam.isMatrixReady())
			{
			//if((System.currentTimeMillis() % 500)==0)
			//System.out.println(System.currentTimeMillis());
			}
		long end=System.currentTimeMillis();
		System.out.println("Start time was "+start+".");
		System.out.println("End time was "+end+".");
		System.out.print("Elapsed time was : ");
		System.out.println(end-start);		
		dists=mam.getMatrix();


		String[] fileLines=new String[sequences.length*2+1];
		for(int pin=0;pin<fileLines.length;pin++)
			{
			fileLines[pin]=new String("");
			}
		fileLines[0]=new String(""+sequences.length+"");
		for(int l=0;l<sequences.length;l++)
			{
			fileLines[l+1]=new String(TreeUtils.removeBadTreeChars(descriptions[l]));
			fileLines[l+1]=removeApostrophesCommasAndColons(fileLines[l+1]);
			}
		int linenum=sequences.length+1;
		for(int ri=1;ri<sequences.length;ri++)
			{
			for(int ci=0;ci<ri;ci++)
				{
				System.out.println("dists r="+ri+" and c="+ci+" is "+dists[ri][ci]+".");
				fileLines[linenum]=fileLines[linenum]+new String(""+dists[ri][ci]+"");
				if(ci!=(ri-1))
					{
					fileLines[linenum]=fileLines[linenum]+new String(",");
					}
				}
			linenum++;
			}

		System.out.println("Here are the file lines :");
		for(int s=0;s<fileLines.length;s++)
			{
			System.out.println(fileLines[s]);
			}

		return fileLines;

		}



	private static String[] getFileLinesFromSerialInput(String serialInput) throws Exception
		{			
		String[] inputSerials=serialInput.split(",");

		if(inputSerials==null || inputSerials.length<=0)
			{
			System.out.println("Error - no serials passed!!!!");
			}
		String[] descriptions=new String[inputSerials.length+1];
		for(int dn=0;dn<descriptions.length-1;dn++)
			{
			descriptions[dn]=TreeUtils.getDataGivenSerialFromServer(inputSerials[dn],"collection_description");
			if(descriptions[dn].trim().length()<=0)
				{
				descriptions[dn]=new String("***No description found in record!****");
				}
			descriptions[dn]=new String(""+inputSerials[dn]+" "+descriptions[dn]);
			System.out.println(descriptions[dn]);
			}
		descriptions[descriptions.length-1]=new String("***Outgroup***");
		String[] sequences=new String[inputSerials.length+1];
		for(int dn=0;dn<sequences.length-1;dn++)
			{
			sequences[dn]=TreeUtils.getDataGivenSerialFromServer(inputSerials[dn],"nucleotide_sequence");
			System.out.println(sequences[dn]);
			}
		sequences[sequences.length-1]=new String("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
		double[][] dists=new double[sequences.length][];


		long start=System.currentTimeMillis();
		AlignmentMaster mam=new AlignmentMaster(sequences,descriptions);
		while(!mam.isMatrixReady())
			{
			//if((System.currentTimeMillis() % 500)==0)
			//System.out.println(System.currentTimeMillis());
			}
		long end=System.currentTimeMillis();
		System.out.println("Start time was "+start+".");
		System.out.println("End time was "+end+".");
		System.out.print("Elapsed time was : ");
		System.out.println(end-start);		
		dists=mam.getMatrix();


		String[] fileLines=new String[sequences.length*2+1];
		for(int pin=0;pin<fileLines.length;pin++)
			{
			fileLines[pin]=new String("");
			}
		fileLines[0]=new String(""+sequences.length+"");
		for(int l=0;l<sequences.length;l++)
			{
			fileLines[l+1]=new String(TreeUtils.removeBadTreeChars(descriptions[l]));
			fileLines[l+1]=removeApostrophesCommasAndColons(fileLines[l+1]);
			}
		int linenum=sequences.length+1;
		for(int ri=1;ri<sequences.length;ri++)
			{
			for(int ci=0;ci<ri;ci++)
				{
				System.out.println("dists r="+ri+" and c="+ci+" is "+dists[ri][ci]+".");
				fileLines[linenum]=fileLines[linenum]+new String(""+dists[ri][ci]+"");
				if(ci!=(ri-1))
					{
					fileLines[linenum]=fileLines[linenum]+new String(",");
					}
				}
			linenum++;
			}

		System.out.println("Here are the file lines :");
		for(int s=0;s<fileLines.length;s++)
			{
			System.out.println(fileLines[s]);
			}

		return fileLines;
		}*/





	private String[] getFileLinesFromMSAFileOnServer(String msaFile)
		{

		try
			{
			URL fileURL=new URL(getCodeBase()+"/"+msaFile);
			String[] MSALines=readStringFromURL(fileURL);

			String[] descriptions=null;
			String[] seqs=null;
			String currentSeq=new String("");

			for(int lineNum=0;lineNum<MSALines.length;lineNum++)
				{
				
				if(MSALines[lineNum].startsWith(">"))
					{
					descriptions=addLine(removeApostrophesCommasAndColons(MSALines[lineNum]),descriptions);
					if(lineNum!=0)
						{
						seqs=addLine(currentSeq,seqs);
						currentSeq=new String("");
						}
					}
				else
					{
					currentSeq=currentSeq+MSALines[lineNum];
					if(lineNum==MSALines.length-1)
						{
						seqs=addLine(currentSeq,seqs);
						}
					}
				}


			for(int d=0;d<seqs.length;d++)
				{
				//System.out.println("Sequence #"+d+" : ");
				//System.out.println(descriptions[d]+"\n"+seqs[d]);
				}

			int targetSeq;
			int gapLen=4;
			int startIndex;
			while(TreeUtils.doesMSANeedTrimming(seqs,gapLen)!=(-1))
				{
				targetSeq=TreeUtils.doesMSANeedTrimming(seqs,gapLen);
				startIndex=TreeUtils.getStartIndexOfLongGap(seqs[targetSeq],gapLen);
				seqs=TreeUtils.trimMSA(seqs,startIndex,startIndex+gapLen);
				}
	
			
			for(int d=0;d<seqs.length;d++)
				{
				//System.out.println("Sequence #"+d+" : ");
				//System.out.println(descriptions[d]+"\n"+seqs[d]);
				}

			double[][] dists=new double[seqs.length][];
			for(int r=0;r<dists.length;r++)
				{
				dists[r]=new double[dists.length];
				for(int c=0;c<dists.length;c++)
					{
					dists[r][c]=TreeUtils.computeDistance(seqs[r],seqs[c]);
					}
				}

			String[] fileLines=new String[seqs.length*2+1];
			fileLines[0]=new String(""+seqs.length+"");
			for(int initNames=0;initNames<seqs.length;initNames++)
				{
				fileLines[initNames+1]=new String(TreeUtils.removeBadTreeChars(descriptions[initNames]));
				fileLines[initNames+1]=removeApostrophesCommasAndColons(fileLines[initNames+1]);
				}
			int linenum=seqs.length+1;
			for(int ri=1;ri<seqs.length;ri++)
				{
				for(int ci=0;ci<ri;ci++)
					{
					System.out.println("dists r="+ri+" and c="+ci+" is "+dists[ri][ci]+".");
					fileLines[linenum]=fileLines[linenum]+new String(""+dists[ri][ci]+"");
					if(ci!=(ri-1))
						{
						fileLines[linenum]=fileLines[linenum]+new String(",");
						}
					}
				linenum++;
				}			




			return fileLines;

			}
		catch(Exception e)
			{
			e.printStackTrace();
			return null;
			}

		}


	public static void busyWait(long millis)
		{
		long end=System.currentTimeMillis()+millis;
		while(System.currentTimeMillis()<end)
			{
			//twiddle thumbs...
			}
		}


	public void init()
		{

		/*Steps to building a tree given a distance matrix and
		sequence names/identifiers :

		1)  Use the given input to build an NJ tree using PAL,
		2)  Use the created tree and find the longest path,
			a)  access the tree using PAL's print method,
			b)  build the tree using the PhyloNode class,
		3)  draw the tree!*/


		//1 & 2)
		//PhyloNode root=TreeUtils.makeARootedNJTreeFromInputData(fileLines);
		WaitFrame myWaitFrame=new WaitFrame("dna_e0.gif");
		System.out.println("Applet being initiated....\n");
		boolean receivedOk=false;
		String[] newickStrings=null;
		while(!receivedOk)
			{
			try
				{
				busyWait(500);
				URL downloadURL=new URL(
								getCodeBase()+getParameter("treeFile")
									);
				System.out.println("The code base is : '"+getCodeBase()+"'.");
				System.out.println("The URL being used to download the tree is : "+downloadURL.toString()+".");
				newickStrings=readStringFromURL(
								downloadURL
								);
				if(newickStrings[newickStrings.length-1].endsWith("DONE"))
					{
					receivedOk=true;
					}
				}
			catch(Exception e)
				{
				e.printStackTrace();
				}

			}
		myWaitFrame.setVisible(false);
		String newickString=new String("");
		for(int c=0;c<newickStrings.length;c++)
			{
			newickString=newickString+newickStrings[c];
			}
		System.out.println("Tree to be built from :`"+newickString+"'.");
		PhyloNode root=TreeUtils.chooseRootAndRootTree(newickString);
		System.out.println("The tree is : \n"+root.toString()+".");

		PhyloCluster rootCluster=new PhyloCluster(root,null,null,true);		
		System.out.println("The rootcluster is : \n"+rootCluster+".");
		//public PhyloCanvas(PhyloCluster root,double scale,double hval,double lval)
		//3)  DRAW THE TREE
		PhyloCanvas pc=new PhyloCanvas(rootCluster,1.0,10,30000,false,this);
		pc.addMouseMotionListener(pc);
		pc.addMouseListener(pc);
		getContentPane().add(pc);
		pc.setNewickString(removeDoneFromEnd(newickString));
		pc.setStaticAppletContext(getAppletContext());
		

		}


	public boolean isInDevelopmentMode()
		{

		try
			{
			String pString=getParameter("devMode");
			if(pString==null)
				{
				return false;
				}
			if(pString.equalsIgnoreCase("yes") || pString.equalsIgnoreCase("1"))
				{
				return true;
				}
			else
				{
				return false;
				}
			}
		catch(Exception e)
			{
			return false;
			}

		}


	public static String removeDoneFromEnd(String n)
		{
		if(n.endsWith("DONE"))
			{
			n=n.substring(0,n.length()-4);
			}
		return n;
		}

	}
