/**
 * 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 java.io.File;
import java.util.HashMap;

public class RunCommandLine {

    ProAlign pa;
    PwAlignment pwa;
    PwAlignmentLoop pwal;
    AlignmentNode root;

    public RunCommandLine(ProAlign pa) throws Exception {

	ProAlign.log("RunCommandLine");

	this.pa = pa;
	SequenceReader sr = new SequenceReader();

	if(pa.seqfile != null && new File(pa.seqfile).exists()) {
	    
	    // ..and it's a valid file,
	    if(sr.fromFile(pa.seqfile)) {
		pa.seqs = sr.getSequences();

		CheckSequence cs = new CheckSequence();
		if(cs.isDna(pa.seqs)){
		    pa.sm.jcDnaModel();
		    ProAlign.isDna = true;
		} else {
		    if(ProAlign.protModel.equals("dayhoff")) {
			pa.sm.dayhoffProteinModel();
		    } else if(ProAlign.protModel.equals("jtt")) {
			pa.sm.jttProteinModel();
		    } else {
			pa.sm.wagProteinModel();
		    }
		    ProAlign.isDna = false;
		}
		if(!cs.isFromAlphabet(pa.seqs,pa.sm.equateAlphabet)) {
		    ProAlign.log.println("Sequence reading error: Illegal characters!");
		    System.out.println("Sequence reading error: Illegal characters!");
		    if(ProAlign.exitInError) {
			System.exit(0);
		    } else {
			throw new Exception("Sequence reading error: Illegal characters");
		    }
		}
	    } else {
		String msg = sr.getErrors();
		ProAlign.log.println(msg);
		System.out.println(msg);
		if(ProAlign.exitInError) {
		    System.exit(0);
		} else {
		    throw new Exception("Sequence reading error");
		}
	    }
	} else {
	    ProAlign.log.println("Sequence file doesn't exist!");
	    System.out.println("Sequence file doesn't exist!");
	    if(ProAlign.exitInError) {
		System.exit(0);
	    } else {
		throw new Exception("Sequence file doesn't exist");
	    }
	}

	String tree = new String();
	TreeReader tr = new TreeReader();

	// do a new tree

	PwSubstitutionMatrix psm = new PwSubstitutionMatrix();
	String pwAlphabet;
	int[][] pwSubst;
	int gOpen, gExt;
	
	if(ProAlign.isDna){
	    pwAlphabet = psm.dnaAlphabet;
	    pwSubst = psm.swdna;
	    gOpen = -1*pa.pwDnaOpen;
	    gExt = -1*pa.pwDnaExt;

	} else {
	    
	    pwAlphabet = psm.protAlphabet;
	    if(pa.pwProtMatrix.equals("pam60")) {
		pwSubst = psm.pam60;
	    } else if(pa.pwProtMatrix.equals("pam160")) {
		pwSubst = psm.pam160;
	    } else if(pa.pwProtMatrix.equals("pam250")) {
		pwSubst = psm.pam250;
	    } else {
		pwSubst = psm.pam120;
	    }
	    gOpen = -1*pa.pwProtOpen;
	    gExt = -1*pa.pwProtExt;
	}

	pwa = new PwAlignment(pwSubst,gOpen,gExt,pwAlphabet,ProAlign.isDna);

	if(pa.doTree) {

	    pwal = new PwAlignmentLoop(pwa,pa.seqs);	    
	    tree = pwal.getTree();

	    if(pa.treefile!=null) {
		try {
		    OutFile newtree = new OutFile(pa.treefile);
		    newtree.println(tree);
		    newtree.close();
		} catch(Exception e) { }

	    }
	    // open an existing tree file
	} else if(pa.treefile != null && new File(pa.treefile).exists()) {

	    String[] treeNodes = tr.getAllNodes(pa.treefile);
	    CheckTreeAndData chk = new CheckTreeAndData(treeNodes,pa.seqs);
	    
	    // ..and it's a valid file, set the tree.
	    if(chk.nodesAreSame()) {
		tree = tr.readFile(pa.treefile);
		if(tr.isUnRooted) {
		    TreeNode tn = new TreeNode(tree);
		    tree = tn.findMiddlePoint();
		}
	    } else {
		ProAlign.log.println("Sequence and tree files don't match!");
		System.out.println("Sequence and tree files don't match!");
		if(ProAlign.exitInError) {
		    System.exit(0);
		} else {
		    throw new Exception("Sequence and tree files don't match");
		}
	    }
	} else {
	    ProAlign.log.println("Tree file doesn't exist!");
	    System.out.println("Tree file doesn't exist!");
	    if(ProAlign.exitInError) {
		System.exit(0);
	    }else {
		throw new Exception("Tree file doesn't exist");
	    }
	}

	
	if(tree != null) {
	    
	    root = new AlignmentNode(pa,tree,0f);

//
	    if(ProAlign.estimateParameters) {
		ParameterEstimates pe = new ParameterEstimates(RunCommandLine.this);

	    }
//

	    try {
		root.align();
	    } catch(TraceBackException tbe) {
		String msg = tbe.getMessage();
		ProAlign.log.println(msg);
		System.out.println(msg);
		if(ProAlign.exitInError) {
		    System.exit(0);
		}else {
		    throw new Exception(msg);
		}
	    } catch(Exception e) {
//		System.out.println("RunCommandLine: throws an exception");
		throw e;
	    }

	    // seems to be fine - save results.
	    
	    if(pa.outformat==1) {
		SaveData sd = new SaveData(pa.outfile,1,root);
	    } else if(pa.outformat==2){
		SaveData sd = new SaveData(pa.outfile,2,root);
	    } else if(pa.outformat==3){
		SaveData sd = new SaveData(pa.outfile,3,root);	    
	    } else if(pa.outformat==4){
		SaveData sd = new SaveData(pa.outfile,4,root);	    
	    }	   

	} else {

	    ProAlign.log.println("Problems with tree!");
	    System.out.println("Problems with tree!");
	    if(ProAlign.exitInError) {
		System.exit(0);
	    } else {
		throw new Exception("Problems with tree");
	    }
	}
    }
}
