#ifndef _NEIGHBOUR_JOINING_H_
#define _NEIGHBOUR_JOINING_H_

#include <iostream>

#include "i_nj_tree_node.h"
#include "distance_matrix.h"
#include "sequences.h"
#include "hi_res_timer.h"
#include "nj_internal_node.h"
#include "nj_leaf_node.h"

#define BUFFER_SIZE 255

using namespace std;
using Data::Sequences;

class NeighbourJoining
{
public:
    NeighbourJoining(const char* filename, DistanceMatrix* dm, Sequences* seq);
    void run();
    void constructTreeFromPhylipFile();

private:
    INJTreeNode* createSubtree(NJInternalNode* node);
    void findLeafNumbers(INJTreeNode* node, INJTreeNode* parent);
    void computeWeights(NJLeafNode** leaves);

    const char* filename; // the file to either write or read tree
    DistanceMatrix* dm;
    Sequences* seq;
    INJTreeNode** orphans; // a pool of nodes without parent (at the end of the algorithm - only root)
    double* Q; // Q matrix needed in the NJ algorithm

    //variables needed to read file to buffer
    char buffer[BUFFER_SIZE];
    int actualLength; // actual number of elements in the buffer
    int bufferPos; // current position in the buffer
    FILE* fd;
    NJLeafNode** leavesPhyl;
    int nLeavesPhyl;

public:
    INJTreeNode* root; // useful to go through the tree
    double* seqsWeights;
    
};

#endif
