package aligner;

import java.io.File;

import fileIO.FileFormat;
import shared.Timer;
import stream.ReadInputStream;
import structures.ByteBuilder;

public class Test {
	
    public static void main(String[] args) {
	    
    	int loops=(args.length>2 ? Integer.parseInt(args[2]) : 400);
    	
	    if (args.length>1) {
	    	String a=args[0], b=args[1];
	        // Align provided sequences
	    	final byte[] seq1=toSequence(a);
	    	final byte[] seq2=toSequence(b);

	    	System.err.println(header());
	    	
//	        test(new GlocalAligner(), "Glocal", seq1, seq2, loops);
	        test(new BandedAligner(), "Banded", seq1, seq2, loops);
	        test(new BandedAlignerM(), "BandedM", seq1, seq2, loops);
	        test(new DriftingAligner(), "Drifting", seq1, seq2, loops);
	        test(new DriftingAlignerM(), "DriftingM", seq1, seq2, loops);
	        test(new QuantumAligner(), "Quantum", seq1, seq2, loops);
	        test(new QuantumAlignerM(), "QuantumM", seq1, seq2, loops);
//	        test(new WaveFrontAligner3(), "WaveFront", seq1, seq2, loops);
//	        test(new SingleStateAlignerFlat2(), "SSA", seq1, seq2, loops);
	        
	    } else {
	        // Demo with 3 test sequences
	    	byte[] seq1="ACGTACGTACGTACGTACGTACGTACGTAC".getBytes();
	    	byte[] seq2="ACGTACTATACGTACGCTACGTACGTACGTC".getBytes(); // Similar with changes
	    	byte[] seq3="TTTGGGCCCAAATTTGGGCCCAAATTTGGG".getBytes(); // Very different
	        int[] pos=new int[2];
	        
	        System.out.println("Seq1-Seq1 int:\t"+GlocalAlignerInt.alignStatic(seq1, seq1, pos));
	        System.out.println("Seq1-Seq2 int:\t"+GlocalAlignerInt.alignStatic(seq1, seq2, pos));
	        System.out.println("Seq1-Seq3 int:\t"+GlocalAlignerInt.alignStatic(seq1, seq3, pos));
	        System.out.println("Seq2-Seq3 int:\t"+GlocalAlignerInt.alignStatic(seq2, seq3, pos));

	        System.out.println("Seq1-Seq1 long:\t"+GlocalAligner.alignStatic(seq1, seq1, pos));
	        System.out.println("Seq1-Seq2 long:\t"+GlocalAligner.alignStatic(seq1, seq2, pos));
	        System.out.println("Seq1-Seq3 long:\t"+GlocalAligner.alignStatic(seq1, seq3, pos));
	        System.out.println("Seq2-Seq3 long:\t"+GlocalAligner.alignStatic(seq2, seq3, pos));

	        System.out.println("Seq1-Seq1 band:\t"+BandedAlignerInt.alignStatic(seq1, seq1, pos));
	        System.out.println("Seq1-Seq2 band:\t"+BandedAlignerInt.alignStatic(seq1, seq2, pos));
	        System.out.println("Seq1-Seq3 band:\t"+BandedAlignerInt.alignStatic(seq1, seq3, pos));
	        System.out.println("Seq2-Seq3 band:\t"+BandedAlignerInt.alignStatic(seq2, seq3, pos));

	        System.out.println("Seq1-Seq1 gloc:\t"+GlocalAlignerOld.alignForward(seq1, seq1));
	        System.out.println("Seq1-Seq2 gloc:\t"+GlocalAlignerOld.alignForward(seq1, seq2));
	        System.out.println("Seq1-Seq3 gloc:\t"+GlocalAlignerOld.alignForward(seq1, seq3));
	        System.out.println("Seq2-Seq3 gloc:\t"+GlocalAlignerOld.alignForward(seq2, seq3));

	        System.out.println("Seq1-Seq1 ssa:\t"+new SingleStateAlignerFlat2().align(seq1, seq1, pos));
	        System.out.println("Seq1-Seq2 ssa:\t"+new SingleStateAlignerFlat2().align(seq1, seq2, pos));
	        System.out.println("Seq1-Seq3 ssa:\t"+new SingleStateAlignerFlat2().align(seq1, seq3, pos));
	        System.out.println("Seq2-Seq3 ssa:\t"+new SingleStateAlignerFlat2().align(seq2, seq3, pos));
	    }
	}
	    
    public static byte[] toSequence(String a) {
    	if(a.length()<100 && new File(a).isFile()) {
    		return ReadInputStream.toReads(a, FileFormat.FA, 1).get(0).bases;
    	}else {return a.getBytes();}
    }
    
    public static String header() {
    	return "Name     \tANI\trStart\trStop\tLoops\tSpace%\tTime";
    }
    
    public static void test(IDAligner ida, String name, byte[] a, byte[] b, int iters) {
    	try {Thread.sleep(1000);}//Cool the CPU 
    	catch (InterruptedException e) {e.printStackTrace();}
    	
    	Timer t=new Timer();
    	float id=0;
    	int[] pos=new int[2];
        for(int i=0; i<iters; i++) {id=ida.align(a, b, pos);}
        long loops=ida.loops()/iters;
        t.stop();
        String time=t.timeInSeconds(3);
        
    	float stateSpace=a.length*b.length;
    	float fraction=loops/stateSpace;
        ByteBuilder bb=new ByteBuilder();
        
        bb.append(name);
        while(bb.length()<9) {bb.append(' ');}
        bb.tab();
        bb.appendt(id, 4);
        bb.appendt(pos[0]);
        bb.appendt(pos[1]);
        bb.appendt(loops);
        bb.appendt(fraction*100, 3);
        bb.append(time);
        System.err.println(bb);
    }
	
}
