/**
 * Title:        ProAlign<p>
 * Description:  <p>
 * Copyright:    Copyright (c) Ari Loytynoja<p>
 * License:      GNU GENERAL PUBLIC LICENSE<p>
 * @see          http://www.gnu.org/copyleft/gpl.html
 * Company:      ULB<p>
 * @author       Ari Loytynoja
 * @version      1.0
 */
package proalign;

import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import java.util.HashMap;
import java.util.Iterator; 
import java.io.File;
import java.util.Calendar;
import java.util.Date;

/** 
 * The main class of ProAlign, the probabilistic alignment program.
 */
public class ProAlign {

    public static double modelDelta = 0.1d;   // HMM
    public static double modelEpsilon = 0.75d; // HMM

    public static double distScale = 1d;      // distance scale factor

    public static double gapFreq = 0.05d;     // prot model gap freq
    public static double gapProb = 0.001d;    // prot model gap subst prob

    public int pwDnaOpen = 1500;       // pw alignment
    public int pwDnaExt = 700;         // pw alignment

    public int pwProtOpen = 1000;      // pw alignment
    public int pwProtExt = 100;        // pw alignment
    public String pwProtMatrix = "pam120";  // pw alignment

    public String treefile = new String();
    public String seqfile;
    public String outfile = new String("proalign.out");

    public boolean nogui = false;
    public boolean doTree = false;
    boolean isAligned = false;

    public int outformat = 2;
    int nodeNumber = -1;
    int defBandWidth;
    int defOffset;

    HashMap seqs;

    public static boolean isDna = true;
    static boolean isResultWindow = false;
    public static boolean trackBest = true; // traceback best
    static boolean DEBUG = true;     // write log
    public static boolean removeTrailing = true; 
    public static boolean penalizeTerminal = true; 
    public static boolean correctMultiple = true; 
    public static boolean writeMin = true;
    public static boolean writeMean = false;
    public static boolean writeAll = false;
    public static boolean writeRoot = false;
    public static boolean estimateGapFreq = false;
    public static boolean estimateGapProb = false;
    public static boolean estimateDelta = false;
    public static boolean estimateEpsilon = false;

    public static boolean exitInError = true;
    public static boolean  estimateParameters = false;
 
    public  static int bandWidth = 101;      // diagonal alignment band width
    public static int offset = 15;

    static String fileExt = new String("paa"); // PA-file extension
    static String version = "0.5 alpha 0";

    public static String protModel = "wag";

    static int paFontSize = 11;
    static String paFontName = "sansserif";

    static String clustalwPath;
    static String folderPath;
    static String tempFolder;

    static int wWidth = 800; // window size
    static int wHeight = 300;

    static OutFile log; 

    public SubstitutionModel sm;
    AlignmentNode root;
    ResultWindow rw;
    
    public ProAlign() {
//	System.out.println("ProAlign");
    }

    public ProAlign(String[] args){

	defBandWidth = bandWidth;
	defOffset = offset;

	startNewLog("proalign.log");
	setUserData();

	if(args.length>0) {
	    ReadArguments ra = new ReadArguments(ProAlign.this, args);
	}
	
	sm = new SubstitutionModel(ProAlign.this);
	if(ProAlign.isDna){
	    sm.jcDnaModel();
	} else {
	    if(ProAlign.protModel.equals("dayhoff")) {
		sm.dayhoffProteinModel();
	    } else if(ProAlign.protModel.equals("jtt")) {
		sm.jttProteinModel();
	    } else {
		sm.wagProteinModel();
	    }
	}

	if(nogui) {
	    try {
		RunCommandLine rcl = new RunCommandLine(ProAlign.this);
	    } catch(Exception e) { }
	} else {

	    rw = new ResultWindow(ProAlign.this);
	    rw.setSize(wWidth,wHeight);
	    isResultWindow = true;
	    rw.setVisible(true);	    

	}
    }

    /**
      * Keeps count on the new nodes that are created. Gives a unique number.
     */
    int getNodeNumber() {
	nodeNumber++;
	return nodeNumber;
    }

    
    /**
      * Resets the counter.
     */
    void setNodeNumber(int i) {
	nodeNumber = i;	
    }


    /**
      * Keep log.
     */
    public void startNewLog(String file) {

	try {                    
	    log = new OutFile(file);
	} catch(Exception e) { }
	
	String date = Calendar.getInstance().getTime().toString();
	log.println("\n------------------------------------");
	log.println("ProAlign - starting a new event log.");
	log.println(" "+date);
	log.println("------------------------------------\n");
	log.flush();
    }


    /**
     * Get userdata from file
     */
    void setUserData() {

	UserSettings user = new UserSettings(); 
        String[] userdata = user.readSettings();
	try {
            if(new File(userdata[0]).isDirectory())
                folderPath = new File(userdata[0]).getAbsolutePath();
        } catch (Exception e) {
            folderPath = new String(".");
        }
        try {
            if(new File(userdata[1]).isFile())
                clustalwPath = new File(userdata[1]).getAbsolutePath();
        } catch (Exception e) {
            clustalwPath = new String("clustalw");
        }
	try {
            if(new File(userdata[2]).isDirectory())
                folderPath = new File(userdata[0]).getAbsolutePath();
        } catch (Exception e) {
	    if(System.getProperty("os.name").startsWith("Windows")){
		tempFolder = "C:\\TEMP";
	    } else {
		tempFolder = "/tmp";
	    }
	}
    }

    static void log(String txt) {
	if(DEBUG) {
	    log.println(txt);
	    log.flush();
	}
    }

    /**
     * Main class. Takes command line arguments to run with scripts.
     */
    public static void main(String[] args) {

	try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) { }
	
	ProAlign pa = new ProAlign(args);
    }
}





