/**
 * 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.io.IOException;
import java.io.InvalidClassException;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

class SampleLoop extends Thread {

    SampleAlignments sl;
    AlignmentNode best;
    AlignmentNode current;
    
    double bestEnd = 0d;

    int currentRun = 0;
    int maxRun;

    SampleLoop(SampleAlignments sl) {

	this.sl = sl;
	current = sl.rw.root;
	maxRun = sl.numRun;

	ProAlign.log("SampleLoop");

	sl.write("\n Sampling "+maxRun+" alignments: ");
	if(sl.writeResults) {
	    String[] names = current.getInternalNames();
	    String str = "number,length,total";
	    for(int i=0; i<names.length; i++) {
		str += ","+names[i];
	    }
	    sl.resultOut.println(str);
	    sl.resultOut.flush();
	}

	start();

    }

    public void run(){
	
	while(sl.isRunning && currentRun < maxRun) {

	    boolean isError = false;
	    String errorMsg = new String();
	    try {
		current.align();
	    } catch(TraceBackException tbe) {
		isError = true;
		errorMsg = tbe.getMessage();
	    } catch(Exception e) { }

	    // Threw an exception during the alignment
	    if(isError) {
		
		OpenDialog od = new OpenDialog(sl);
		od.showDialog("Error!", "\n  "+errorMsg+"\n  Try to increase the band width.\n");
		break;

	    } else {
		
		if(current.isBandWarning()) {
		    sl.write("Traceback path came very close\n  to the band edge."+
			     " Alignment may\n  not be the correct one!");
		}
		
	    }

	    if(currentRun==0) {
		bestEnd = current.sumViterbiEnd();
		sl.rw.root = current;
		sl.rw.setAlignedData(sl.rw.root);
		sl.rw.setScrollPanes();
		sl.rw.messageText.setText(" Sample "+(currentRun+1)+"/"+maxRun+": "+current.sumViterbiEnd());

	    } else if (current.sumViterbiEnd() > bestEnd) {
		bestEnd = current.sumViterbiEnd();
		sl.rw.root = current;
		sl.rw.setAlignedData(sl.rw.root);
		sl.rw.setScrollPanes();
		sl.rw.messageText.setText(" Sample "+(currentRun+1)+"/"+maxRun+": "+current.sumViterbiEnd());
	    }
	    if(sl.writeAlignments) {

		String path = sl.folderPath+File.separator+(currentRun+1)+"."+ProAlign.fileExt;
		try {
		    ObjectOutputStream os =
			new ObjectOutputStream(new FileOutputStream(path));
		    os.writeObject((AlignmentNode) current);
		    os.flush();
		    os.close();
		} catch(IOException ioe) {
		    ProAlign.log.println("Sample exception1: "+path+"\n"+ioe.toString());
		    ProAlign.log.flush();
		    //ioe.printStackTrace();
		}
		catch(Exception oe) {
		    ProAlign.log.println("Sample exception2: "+path+"\n"+oe.toString());
		    ProAlign.log.flush();
		    //oe.printStackTrace();
		}
	    }

	    if(sl.writeNexus) {
		String path = sl.nexusPath+File.separator+(currentRun+1)+".nex";
		SaveData sd = new SaveData(path,1,current);
	    }
	    if(sl.writeFasta) {
		String path = sl.fastaPath+File.separator+(currentRun+1)+".pir";
		SaveData sd = new SaveData(path,2,current);
	    }

	    sl.write("Sample "+(currentRun+1)+"/"+maxRun+": "+current.sumViterbiEnd()+"; best: "+bestEnd);

	    if(sl.writeResults) {

		double[] vit = current.getInternalViterbiEnd();
		String str = (currentRun+1)+","+current.cellPath.length+","+current.sumViterbiEnd();
		for(int i=0; i<vit.length; i++) {
		    str += ","+vit[i];
		}
		sl.resultOut.println(str);
		sl.resultOut.flush();
	    }
	    if(ProAlign.DEBUG) {
		ProAlign.log.println(" sample number "+currentRun);
		ProAlign.log.flush();
	    }

	    currentRun++;
	}
    }
}
