#ifndef _I_NJ_TREE_NODE_H_
#define _I_NJ_TREE_NODE_H_

#include <malloc.h>

class INJTreeNode;

class INJTreeNodeList
{
public:
    INJTreeNode* current;
    INJTreeNodeList* next;

    ~INJTreeNodeList()
    {
        if (next != NULL)
            delete next;
    }
};

class INJSequencesNoListElement
{
public:
    int seqNo;
    INJSequencesNoListElement* next;

    ~INJSequencesNoListElement()
    {
        if (next != NULL)
            delete next;
    }
};

class INJSequencesNoList
{
public:
    int* toArray()
    {
        int* result = new int[count];
        INJSequencesNoListElement* elem = first;
        for (int i = 0; i < count; i++)
        {
//            if (elem == NULL)
//                break;

            result[i] = elem->seqNo;

            elem = elem->next;
        }
        return result;
    }

    ~INJSequencesNoList()
    {
        delete first;
    }

    INJSequencesNoListElement* first;
    int count;
};

class INJTreeNode
{
public:
    //memoryForString: array of char where tree will be written
    //offset: where to write
    //totalElementsCount: number of elements in memoryForString array in total
    virtual void ToString(char*& memoryForString, int& offset, int& totalElementsCount) = 0;

    virtual int maxHeight() = 0;

    virtual INJTreeNodeList* collectNodes(int height, INJTreeNodeList* list = NULL) = 0;

    virtual INJSequencesNoList* collectSequenceNumbers(INJSequencesNoList* list = NULL) = 0;

    //value of the node (to check)
    double value; //distance to the parent node

    int length; // length of sequence (in leaf) or alignment (in internal node)

    bool isLeaf; // only to determine if a given node is NJInternalNode or NJLeafNode

    int numOfLeaves;
    INJTreeNode* parent;


    static void setIsLeaf(INJTreeNode* This, bool isLeaf);
    static void setValue(INJTreeNode* This, double value);

    void resizeMemoryIfNeeded(char*& memoryForString, int& offset, int& totalElementsCount)
    {
        if (totalElementsCount - offset < 1100) //1100 - max length of seq name + space for value
        {
            totalElementsCount += 8192;
            memoryForString = (char*)realloc(memoryForString, totalElementsCount);
        }
    }
};

#endif
