#include "nj_internal_node.h"
#include <stdio.h>
#include <algorithm>

using namespace std;

NJInternalNode* NJInternalNode::createNJInternalNode()
{
    return new NJInternalNode();
}


void NJInternalNode::setChildNodeLeft(NJInternalNode* This, INJTreeNode* node)
{
    This->childNodeLeft = node;
}

void NJInternalNode::setChildNodeRight(NJInternalNode* This, INJTreeNode* node)
{
    This->childNodeRight = node;
}

void NJInternalNode::ToString(char*& memoryForString, int& offset, int& totalElementsCount)
{
    // format:
    //
    // (
    // sequence127:0.14132,
    // sequence191:0.13868)
    // :0.00646
    
    this->resizeMemoryIfNeeded(memoryForString, offset, totalElementsCount);
    memoryForString[offset++] = '(';
    memoryForString[offset++] = '\n';
    this->childNodeLeft->ToString(memoryForString, offset, totalElementsCount);
    this->resizeMemoryIfNeeded(memoryForString, offset, totalElementsCount);
    memoryForString[offset++] = ',';
    memoryForString[offset++] = '\n';
    this->childNodeRight->ToString(memoryForString, offset, totalElementsCount);
    this->resizeMemoryIfNeeded(memoryForString, offset, totalElementsCount);
    memoryForString[offset++] = ')';
    memoryForString[offset++] = '\n';
    sprintf(&(memoryForString[offset]), ":%.5f", value);
    offset+=8;
}

int NJInternalNode::maxHeight()
{
    return max(this->childNodeLeft->maxHeight(), this->childNodeRight->maxHeight())+1;
}

INJTreeNodeList* NJInternalNode::collectNodes(int height, INJTreeNodeList* list)
{
    height--;

    if (height == 0)
    {
        INJTreeNodeList* newNode = new INJTreeNodeList();
        newNode->current = this;
        newNode->next = list;

        list = newNode;
    }
    else // height > 0
    {
        list = this->childNodeLeft->collectNodes(height, list);
        list = this->childNodeRight->collectNodes(height, list);
    }

    return list;
}

INJSequencesNoList* NJInternalNode::collectSequenceNumbers(INJSequencesNoList* list)
{
    list = this->childNodeLeft->collectSequenceNumbers(list);
    list = this->childNodeRight->collectSequenceNumbers(list);
    return list;
}

void NJInternalNode::determineLeavesNumber(NJInternalNode* This)
{
    This->numOfLeaves = This->childNodeLeft->numOfLeaves + This->childNodeRight->numOfLeaves;
}

