// Change History:


#ifndef DDP_VECTOR_H
#define DDP_VECTOR_H

#include  "ddp_descr.h"
#include  "drs/drs_appl.h"
#include  "drs/drs_vect.h"

////////////////////////////////////////////////////////
// DDP_VectorTree class
////////////////////////////////////////////////////////
class DDP_VectorTree
{
public:
    class Node : public DDP_Descr
        {
    private:
        uint NodeID;
        uint Depth;
        bool Offset;
        std::vector<const Node *> Children;

    public:
        Node() : NodeID(0), Depth(0), Offset(false) {}
        Node(const byte * caption, const byte * sshort = NULL, const byte * id = NULL) :
            DDP_Descr(caption, sshort, id), NodeID(0), Depth(0),
            Offset(false) {}
        Node(const DRS_Descriptor * descr) : NodeID(0), Depth(0), Offset(false)
            { if(!descr) return;
                SetCaption((const byte *)descr->Caption); 
				SetShort((const byte *)descr->Descr); 
				SetID((const byte *)descr->ID); }

        virtual ~Node() { Clear(); }

        uint GetChildrenCount() const { return Children.size(); }
        const Node * GetChild(uint num) const { if(Offset) ++num;
            return num < GetChildrenCount() ?
            Children[num] : NULL; }
        const Node * GetChild(const byte * str) const;

        uint GetNodeID() const { return NodeID; }
        void SetNodeID(uint id) { NodeID = id; }

        uint GetDepth() const { return Depth; }
        void SetDepth(uint depth) { Depth = depth; }

        Node * AddChild(const byte * caption, const byte * sshort, const byte * id);
        Node * AddChild(const DRS_Descriptor * descr) {
            return AddChild((const byte *)descr->Caption, (const byte *)descr->Descr, (const byte *)descr->ID); }

        bool IsOffset() const { return Offset; }
        void SetOffset(bool off) { Offset = off; }

        virtual void Clear();
        };
        
public:
    class Formula : public DDP_Descr
    {
    private:
        bool bIsSumable;
        bool bIsQuantile;
        uint Size;
        uint TextSize;
        AT_Num MaxValue;
        
    public:
        Formula() : bIsSumable(false), bIsQuantile(false), Size(0), TextSize(0), MaxValue(0) {}
        Formula(const byte * caption, const byte * sshort = NULL, const byte * id = NULL) :
            DDP_Descr(caption, sshort, id), bIsSumable(false), bIsQuantile(false), MaxValue(0) {}
        Formula(const DDP_Descr & rhs) : DDP_Descr(rhs), bIsSumable(false), bIsQuantile(false), MaxValue(0) {}
        Formula(const Formula & rhs) : DDP_Descr(rhs),
            bIsSumable(rhs.bIsSumable), bIsQuantile(rhs.bIsQuantile), MaxValue(0) {}
        Formula(const DRS_Descriptor * descr) : bIsSumable(false), bIsQuantile(false), MaxValue(0)
            { if(!descr) return;
                SetCaption((const byte *)descr->Caption); 
				SetShort((const byte *)descr->Descr); 
				SetID((const byte *)descr->ID); }
        virtual ~Formula() {}

        void SetSumable(bool bsum) { bIsSumable = bsum; }
        bool GetSumable() const { return bIsSumable; }

        void SetQuantile(bool q) { bIsQuantile = q; }
        bool GetQuantile() const { return bIsQuantile; }

        void SetDataSize(uint sz) { Size = sz; }
        uint GetDataSize() const { return Size; }

        void SetDataTextSize(uint sz) { TextSize = sz; }
        uint GetDataTextSize() const { return TextSize; }

        void SetMaxValue(AT_Num num) { MaxValue = num; }
        AT_Num GetMaxValue() const { return MaxValue; }
    };

public:
    class FormulaCollection : public DDP_DescrCollection
    {
    protected:
        virtual DDP_Descr * CreateObject() const { return new Formula; }
        virtual DDP_Descr * CreateObject(uint num) const { const DDP_Descr * descr = Get(num);
            return descr ? new Formula(*descr) : NULL; }
    public:
        FormulaCollection() : DDP_DescrCollection() {}
        FormulaCollection(const FormulaCollection &rhs) : DDP_DescrCollection(rhs) {}

        virtual bool GetSumable(uint num) const {  const Formula * f = (const Formula *)Get(num);
            return f ? f->GetSumable() : false; }
        virtual void SetSumbale(uint num, bool sum) { Formula * f = (Formula *)Get(num);
            f->SetSumable(sum); }

        virtual bool GetQuantile(uint num) const {  const Formula * f = (const Formula *)Get(num);
            return f ? f->GetQuantile() : false; }
        virtual void SetQuantile(uint num, bool bq) { Formula * f = (Formula *)Get(num);
            f->SetQuantile(bq); }
    };

public:
    class RootNode : public Node
        {
    private:
        FormulaCollection Formulas;
        DDP_DescrCollection IndexStates;
        DDP_DescrCollection Periods;
        uint MaxDepth;
        uint DataSize, DataTextSize;

    public:
        RootNode() : MaxDepth(0), DataSize(0), DataTextSize(0) { SetDepth(-1); }
        RootNode(const byte * caption, const byte * sshort = NULL, const byte * id = NULL) :
            Node(caption, sshort, id), MaxDepth(0) , DataSize(0), DataTextSize(0)
            { SetDepth(-1); }
        RootNode(const DRS_Descriptor * descr) : Node(descr), MaxDepth(0),
            DataSize(0), DataTextSize(0)
            { SetDepth(-1); }

        virtual ~RootNode() {}

        void AddFormula(const byte * caption,
            const byte * sshort = NULL, const byte * id = NULL) { Formulas.Add(caption,
            sshort, id); }
        void AddFormula(const DRS_Descriptor * descr, bool bsum, bool bq) { if(!descr) return;
            AddFormula((const byte *)descr->Caption, (const byte *)descr->Descr, (const byte *)descr->ID);
            Formula * f = (Formula *)GetFormula(GetFormulaCount() - 1);
            if(f) {f->SetSumable(bsum); f->SetQuantile(bq); } }
        void AddIndexState(const byte * caption,
            const byte * sshort = NULL, const byte * id = NULL) { IndexStates.Add(caption,
            sshort, id); }
        void AddIndexState(const DRS_Descriptor * descr) { if(!descr) return;
            AddIndexState((const byte *)descr->Caption, (const byte *)descr->Descr, (const byte *)descr->ID); }

        void AddPeriod(const byte * caption,
            const byte * sshort = NULL, const byte * id = NULL) { Periods.Add(caption,
            sshort, id); }
        void AddPeriod(const DRS_Descriptor * descr) { if(!descr) return;
            AddPeriod((const byte *)descr->Caption, (const byte *)descr->Descr, (const byte *)descr->ID); }

        uint GetMaxDepth() const { return MaxDepth; }
        void SetMaxDepth(uint depth) { MaxDepth = depth; }
        
        uint GetFormulaCount() const { return Formulas.GetCount(); }
        uint GetIndexStateCount() const { return IndexStates.GetCount(); }

        const Formula * GetFormula(uint num) const { return (const Formula *)Formulas.Get(num); }
        bool GetSumable(uint num) const { return Formulas.GetSumable(num); }
        bool GetQuantile(uint num) const { return Formulas.GetQuantile(num); }        
        const Formula * GetFormula(const byte * str) const { return (const Formula *)Formulas.Get(str); }

        const DDP_Descr * GetIndexState(uint num) const { return IndexStates.Get(num); }
        const DDP_Descr * GetIndexState(const byte * str) const { return IndexStates.Get(str); }

        uint GetPeriodCount() const { return Periods.GetCount(); }
        const DDP_Descr * GetPeriod(uint num) const { return Periods.Get(num); }
        const DDP_Descr * GetPeriod(const byte * str) const { return Periods.Get(str); }

        uint GetDataSize() const { return DataSize; }
        void SetDataSize(uint sz) { DataSize = sz; }

        uint GetDataTextSize() const { return DataTextSize; }
        void SetDataTextSize(uint sz) { DataTextSize = sz; }
        };

private:
    std::vector<RootNode *> Roots;
    std::vector<VectorAddress> Address;

    uint Size;
    uint TextSize;
    
private:
    struct DRS_Node
        {
        const DRS_VectorNode * Node;
        const DRS_VectorDim  * Dim;
        const DRS_Vector * Vector;
        };
    bool LoadRoot(const DRS_Vector * vector);
    bool RecursiveAddNode(Node * ddp_node, DRS_Node & drs_node);
    VectorAddress * get_address() const { return Address.size() ?
        (VectorAddress *)&Address[0] : NULL; }
    bool is_offset(const DRS_Vector * vector, uint depth) const;
    
public:
    DDP_VectorTree() : Size(0), TextSize(0) {}
    ~DDP_VectorTree() { Clear(); }
    
    bool LoadTree(const DRS_Application * app);

    uint GetRootCount() const { return Roots.size(); }
    const RootNode * GetRoot(uint i) const { return i < GetRootCount() ?
        Roots[i] : NULL; }
    virtual void Clear();

    uint GetDataSize() const { return Size; }
    uint GetDataTextSize() const { return TextSize; }
};

#endif

 