import cs201j.*;
import java.util.*;
import java.io.*;

public class Phylogeny {

    public static void main (/*@non_null@*/ String [] args) {
	// EFFECTS: If args has one element that is the name of a file
	//    containing one or more lines of the form <species> <genome>
	//    (where the same species does not appear more than once)
	//    prints out a tree with the first species in the file as the
	//    root such that all other species in the file are in the tree,
	//    and this tree has the lowest possible parsimony score (as
	//    defined in the PS4 handout).
	//
	//    If there is not exactly one element in the args array, or
	//    the element does not name a correctly formatted file, prints
	//    a warning and exits.
	//

	if (args.length != 1) {
	    System.err.println ("Usage: java Phylogeny <file>");
	    System.exit (1);
	}

	SpeciesSet s = new SpeciesSet ();
	Species root = null;

	try {
	    BufferedReader reader = new BufferedReader (new FileReader (args[0]));
	    String line;

	    while ((line = reader.readLine ()) != null) {
		StringTokenizer st = new StringTokenizer (line);
		
		if (st.hasMoreTokens ()) {
		    String speciesname = st.nextToken ();
		    
		    if (st.hasMoreTokens ()) {
			String genome = st.nextToken ();
			
			if (root == null) {
			    root = new Species (speciesname, new Genome (genome));
			} else {
			    if (s.isIn (speciesname) || root.getName ().equals (speciesname)) {
				System.err.println ("Duplicate species in file: " + speciesname);
				System.exit (1);
			    } else {
				s.insert (new Species (speciesname, new Genome (genome)));
			    }
			}

			if (st.hasMoreTokens ()) {
			    System.err.println ("Badly formatted line (extra text after genome): " + line);
			    System.exit (1);
			}
		    } else {
			System.err.println ("Badly formatted line (no genome): " + line);
			System.exit (1);
		    }
		} else {
		    ; 
		}
	    }

	    if (root == null) {
		System.err.println ("No root species (empty file)");
		System.exit (1);
	    }
	} catch (FileNotFoundException fnfe) {
	    System.err.println ("Cannot open file: " + args[0]);
	    System.exit (1);
	}  catch (IOException ioe) {
	    System.err.println ("Error reading file: " + ioe);
	    System.exit (1);
	}

	// System.err.println ("Loaded " + s.size () + " species: " + s);
	SpeciesTreeSet alltrees = AllTrees.allTreesRoot (s, root);
	SpeciesTree besttree = null;
	int bestresult = -1;

	// System.err.println ("Trying all trees: " + alltrees.size ());
	Enumeration treeiter = alltrees.elements ();
	//@set treeiter.elementType = \type (SpeciesTree) ; 
	//@set treeiter.returnsNull = false ;
	
	while (treeiter.hasMoreElements ()) {
	    SpeciesTree btree = (SpeciesTree) treeiter.nextElement ();
	    
	    int pvalue = btree.parsimonyValue ();
	    
	    if (besttree == null) {
		besttree = btree;
		bestresult = pvalue;
	    } else if (pvalue < bestresult) {
		besttree = btree;
		bestresult = pvalue;
	    } else {
		// keep the old best tree
	    }
	}
	
	System.out.println ("Best tree: \n" + besttree);
	System.out.println ("Parsimony value: " + bestresult);
    }
}