#ifndef Needle_H
#define Needle_H

#include "ProbModel.h"


/*Needleman Wunsch Algorithm*/
enum DIRS{DIR_DIAG=0,DIR_LEFT,DIR_UP};

class DIRTracks{
 protected:
 	DIRS defVal;
 	DIRS dirs[3];
 
 public:
 	DIRTracks(){defVal=DIR_DIAG;};
 	~DIRTracks(){};
 	DIRS GetVal(DIRS id) { return dirs[id];};
	void SetVal(DIRS id,DIRS val) { dirs[id]=val;};
	DIRS GetEntry(){return defVal;};
	DIRS GetEntryVal(){return dirs[defVal];};
	void SetEntry(DIRS id){defVal=id;};
};

class VTracks{
 protected:
 	REAL vals[3];
 
 public:
 	VTracks(){};
 	~VTracks(){};
 	REAL GetVal(DIRS id) { return vals[id];};
	void SetVal(DIRS id,REAL val) { vals[id]=val;};
	
	VTracks & operator = (const VTracks  & v)
	{
		for (int i=0;i<3;i++) 
		  vals[i]=v.vals[i];
		return *this;
	}
	DIRS GetMaxInc(REAL ia, REAL ib, REAL ic, REAL &newval);
};


class Needle{
	protected:
	REAL gap_open;
	REAL gap_len; 
	REAL score;
	int Diag;
	
	int* StrToCode(char* str); 
	REAL Score(int row, int col); 
	REAL Score(ProbChar &p1, ProbChar &p2);
	REAL Score(int row, ProbChar &p2);


	void GetAlignments(DIRTracks *pr, ProbString &sA, ProbString &sB, ProbString &alA,ProbString &alB);
	void GetAlignments(DIRTracks *pr, char *sA, char *sB, char *alA,char *alB);
	void GetAlignments(DIRTracks *pr, char *sA, ProbString &sB, char *alA,ProbString &alB);
	void GetAlignments(DIRTracks *pr, ProbString &sA, ProbString &sB, ProbString &alA,ProbString &alB, int *posA, int *posB);

	REAL CalculateMatrix(ProbString &source, ProbString &dest, int slen, int dlen, DIRTracks *pr);
	REAL CalculateMatrix(int* source, int* dest, int slen, int dlen, DIRTracks *pr);

	REAL CalculateMatrix_Diag(ProbString &source, ProbString &dest, int slen, int dlen, int diag_dn, int diag_up, DIRTracks *pr);
	REAL CalculateMatrix_Diag(int *source, ProbString &dest, int slen, int dlen, int diag_dn, int diag_up, DIRTracks *pr);
	REAL CalculateMatrix_Diag(int* source, int* dest, int slen, int dlen, int diag_dn, int diag_up, DIRTracks *pr);
	REAL CalculateMatrix_NoDgap(int *source, ProbString &dest, int slen, int dlen, DIRTracks *pr);
	

	public:
		Needle(REAL go, REAL gl, int dg=0)
		{
			gap_open=-1*go;
			gap_len=-1*gl;
			Diag=dg;
		};
		~Needle(){};
		void Align(ProbString &str1,ProbString &str2,ProbString &al1, ProbString &al2, REAL diag_fact);
		void Align(char *seq1,char *seq2,char *al1, char *al2, REAL diag_fact); 
		void Align(char *seq1,ProbString &str2,char *al1, ProbString &al2, REAL diag_fact);		
		void Align(ProbString &str1,ProbString &str2,ProbString &al1, ProbString &al2, int* pos1, int *pos2, REAL diag_fact);
		void AlignToTemp(char *seq1,ProbString &str2,char *al1, REAL diag_fact);		
};

#endif
