// Change History:

#include "ddp/ddp_vector.h"
//#include "drs_appl.h"
#include "drs/drs_formula.h"


// **************************************************************************
// DDP_VectorTree
// **************************************************************************

//--------------------------------------------------------------------------

void DDP_VectorTree::Node::Clear()
{
    Offset = false;
    Depth = 0;
    NodeID = 0;
    
    uint i, cnt = GetChildrenCount();
    for(i = 0; i < cnt; ++i)
        {
        Node * child = (Node *)GetChild(i);
        if(child)
            delete child;
        }
    Children.clear();
}
//--------------------------------------------------------------------------

DDP_VectorTree::Node * DDP_VectorTree::Node::AddChild(const byte * caption,
    const byte * sshort, const byte * id)
{
    Node * child = new Node(caption, sshort, id);
    child->SetDepth(Depth + 1);
    uint num = GetChildrenCount();
    child->SetNodeID(num);

    Children.push_back(child);
    
return child;
}
//--------------------------------------------------------------------------

const DDP_VectorTree::Node *
DDP_VectorTree::Node::GetChild(const byte * str) const
{
    if(!str)
        return NULL;

    if(*this == str)
        return this;

    uint i, cnt = GetChildrenCount();
    for(i = 0; i < cnt; ++i)
        {
        const Node * node = GetChild(i);
        const Node * child = node->GetChild(str);
        if(child)
            return child;
        }

return NULL;
}
//--------------------------------------------------------------------------

bool DDP_VectorTree::LoadTree(const DRS_Application * app)
{
    if(!app)
        return false;
        
    Address.resize(app->MaxVectorDepth() + 1, 0);

    Clear();
    uint i, cnt = app->VectorCount();
    for(i = 0; i < cnt; ++i)
        {
        const DRS_Vector * vector = &app->Vector(i);
        if(!LoadRoot(vector))
            return false;

        Size     = max(vector->GetDataSize(), Size);
        TextSize = max(vector->GetDataTextSize(), TextSize);
        }

return true;        
}
//--------------------------------------------------------------------------

bool DDP_VectorTree::LoadRoot(const DRS_Vector * vector)
{
    if(!vector)
        return false;
    const DRS_Descriptor * descr = &vector->Descriptor();
    RootNode * root = new RootNode(descr);

    // load formulas
    uint i, cnt = vector->FormulaCount();
    for(i = 0; i < cnt; ++i)
        {
        uint fi = root->GetFormulaCount();
        const DRS_Formula * formula = &vector->Formula(i);
        descr = &formula->Descriptor();
        root->AddFormula(descr, formula->IsSumable(), formula->IsQuantile());
        Formula * f = (Formula *)root->GetFormula(fi);
        f->SetDataSize(formula->GetDataSize());
        f->SetDataTextSize(formula->GetDataTextSize());
        f->SetMaxValue(formula->GetMaxValue());
        }
    // load index states
    cnt = vector->IndexStateCount();
    for(i = 0; i < cnt; ++i)
        {
        const DRS_Descriptor * index_state = &vector->IndexStateDescr(i);
        root->AddIndexState(index_state);
        }

    // load periods
    cnt = vector->PeriodCount();
    for(i = 0; i < cnt; ++i)
        {
        descr = &vector->Period(i);
        root->AddPeriod(descr);
        }
    root->SetNodeID(vector->VectorID());
    DRS_Node node;
    node.Node = vector->GetRootNode();
    node.Vector = vector;
    const DRS_VectorDim * dim = &vector->Dim(0);
    node.Dim = dim->GetChild();

    root->SetMaxDepth(vector->Depth());
    root->SetDataSize(vector->GetDataSize());
    root->SetDataTextSize(vector->GetDataTextSize());

    if(!RecursiveAddNode(root, node))
        return false;
        
    Roots.push_back(root);

return true;
}
//--------------------------------------------------------------------------

bool DDP_VectorTree::RecursiveAddNode(Node * ddp_node, DRS_Node & drs_node)
{
    const DRS_VectorNode * vector_node = drs_node.Node;
    const DRS_Vector * vector = drs_node.Vector;
    const DRS_VectorDim * dim = drs_node.Dim;

    if(!dim)
        return true;
        
    uint i, cnt = 0;
    if(vector_node)
        {
        cnt = vector_node->ChildCount();
        if(!cnt)
            vector_node = NULL;
        }
    if(!cnt)
        cnt = dim->MaxLength();

    for(i = 0; i < cnt; ++i)
        {
        const DRS_Descriptor * descr;
        bool off = is_offset(vector, ddp_node->GetDepth() + 1);
        ddp_node->SetOffset(off);        
        if(vector_node)
            {
            drs_node.Node = vector_node->GetChild(i);
            if(off && !i)
                descr = &dim->NodeDescr(*vector, -1);
            else
                descr = &drs_node.Node->Descriptor();
            }
        else
            {
            drs_node.Node = NULL;
            descr = &dim->NodeDescr(*vector, off ? i - 1 : i);
            }
        Node * child = ddp_node->AddChild(descr);
        if(!child)
            return false;
        // set offest to child
        drs_node.Dim = dim->GetChild();
        if(!RecursiveAddNode(child, drs_node))
            return false;
        }
return true;
}
//--------------------------------------------------------------------------

bool DDP_VectorTree::is_offset(const DRS_Vector * vector, uint depth) const
{
    // if( depth == 0) return false;

    const DRS_VectorDim * dim = &vector->Dim(depth + 1);
    const DRS_VectorDim * parent_dim = &vector->Dim(depth);

return dim->IsCollective() && parent_dim->IsMappedToChild();
}
//--------------------------------------------------------------------------

void DDP_VectorTree::Clear()
{
    uint i, cnt = GetRootCount();
    for(i = 0; i < cnt; ++i)
        {
        RootNode * root = (RootNode *)GetRoot(i);
        delete root;
        }
        
    Roots.clear();
}

/****************************************************************************
 NOTES
 ****************************************************************************/
