#ifndef PROBCLUSTER_H
#define PROBCLUSTER_H
#include "ProbModel.h"
#include "ProbTree.h"
#include <fstream>
#include <set>
using namespace std;

class ClusterRecord{
public:
	Tree *Node;
	int ID;
	int NNseq; //my nearest neighbour;
	int NumSeqs;
	set<unsigned int> NNlist; //indice of CRs who register me as NN
	set<unsigned int> Seqlist; //sequence IDs
	int clsid;
	REAL NNdist;
	REAL distErr;
	int tagscan;
};

class ProbCluster{
	 Tree * root;
	 REAL levelmin;
	 REAL levelinc;
	 REAL levelmax;
	 REAL levelcurrent;
	 REAL maxdist;
	 ClusterRecord *clRec;
	 int NumCls;
	 int clistTop;
		
	 Tree *CreateBranch(unsigned int uid,int frq,REAL levelup);
	 Tree *CreateBranch(Tree *node,REAL levelup);
	 void AddRecord(unsigned int uid, Tree *node);
	 
	 public:
	 	ProbCluster(REAL lmin,REAL lmax);

	 	~ProbCluster() { if (root) delete root;};
	 	
	 	void InitCluster(int SeqNum);
	 	void Finish();

	 	void AddSeq(unsigned int uid, int frq=1);
	 	Tree *MergeNode(Tree *node1,Tree *node2, unsigned int uid);
	 	Tree *FindCommonParent(Tree *node1,Tree *node2);
	 	void AddNode(Tree *node,Tree *top,int id1=-1,int id2=-1,int sq1=0,int sq2=0);
	 	void DeleteNode(Tree *node,Tree *top);
		
	 	void CondenseBottom();
	 	void NNSearch(int uid,bool exactsearch=false,int id1=-1,int id2=-1,int sq1=0,int sq2=0);
		void BuildNNlist();

		void Print( fstream & out) 
			{if (root) root->Print(out);};
		void Brief( fstream & out)
			{root->Brief(out,0,1);};
		void PrintNN(fstream & out, int SeqNum); 
		void GenDist(fstream & fdist, fstream & fgroup, REAL leveltop, REAL levelbase);
		void ReportList(fstream &flist,fstream & fstat, fstream &fgroup, REAL leveldown, REAL levelup);
		void HCluster(fstream &flist,fstream & fstat, fstream &fgroup);
		void Report(fstream &flist,fstream &fstat,fstream &fgroup);
};

#endif
