// Change History
// 11/20/03 AV Development: BC6 conversion. Const/none const

#ifndef _DRS_RPT_H_
#define _DRS_RPT_H_

//////////////////////////////////////////////////////////////////////////////////////////////////////////
// DRS_Report
//////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
Create a ReportTree.
Add Subreports to the ReportTree as SearchFieldIDs.
Add VectorID/VectorAddresses to the ReportTree.
Generate the report by passing a RecordList to the report.
*/
/*
A ReportTree creates a root ReportNode. The root report node creates a
ReportVectorTree for each vector added. Vector Addresses
are added to the ReportVectorTree as a nodal system.

On generate, the ReportTree creates a clean copy of the root ReportNode used
for loading records. It loads each record into its copy and adds this to
the root ReportNode. Each ReportNode then adds the copy to either the current child
or a new child (IFF not destined for curr child).

Copy ReportNpode->copy ReportVector->copy ReportVectorNode appears to not
be adding children correctly.
*/


#include "drs_vect.h"
#include "drs_appl.h"
#include "drs_tree.h"
#include "drs_data.h"

#include "drs_fld.h"

const uint32 REPORTVECTORSUMNODE_ID = (uint32)-1;

class DRS_ReportTree;
class DRS_ReportNode;
class DRS_ReportDim;
class DRS_ReportVectorTree;
class DRS_ReportVectorTreeNode;
class DRS_ReportVectorTreeDim;


class DRS_ReportDim : public DRS_TreeDim<DRS_ReportDim>
{
  public:
  //Undefined, i.e. dummy root
  DRS_ReportDim()
     {};
          //, DRS_TreeDim<DRS_ReportDim>()
  DRS_ReportDim( DRS_Field const &rField) : pFieldData( new DRS_FieldData( rField)), DRS_TreeDim<DRS_ReportDim>( rField.Descriptor())
    {};

  void operator<< ( DRS_RecordSet &rec) const;
  inline DRS_FieldData const & FieldData() const { return *pFieldData;};

  private:
  auto_ptr<DRS_FieldData> pFieldData;
};

class DRS_ReportNode : public DRS_TreeNode<DRS_ReportNode>
{
  friend DRS_ReportNode;
  friend DRS_ReportTree;

  public:
  DRS_ReportNode()
    {};
  //Copy contructor
  DRS_ReportNode( DRS_ReportNode const &rCopyNode);
  //Copy for new subreport.
  //A reportNode creates a new ReportNode from the load data report node when a new ReportDim value is detected
  //and attaches as child.
  DRS_ReportNode( DRS_ReportNode const &rCopyNode, DRS_FieldData const * pFieldData);

  ~DRS_ReportNode();

  inline void AttachVectorTree( DRS_ReportVectorTree *p)
    {
    vReportVectors.push_back( p);
    };

  void operator<< ( DRS_RecordSet &rRecord);
  void Clear();
  void PlusEquals( DRS_ReportNode const &rNode, DRS_ReportDim const *pDim);
  void SetResult( DRS_ReportNode const &rNode, DRS_ReportDim const *pDim);

  inline DRS_ReportVectorTree const & ReportVector( uint i) const { return(*vReportVectors[i]);};
         DRS_FieldData const * FieldData() const { return pFieldData.get(); };

  //Retrieval
  inline uint VectorCount() const { return vReportVectors.size();};

  void Debug( FILE *hFile)
    {
    fprintf( hFile, "Report node has %u report vectors\n", vReportVectors.size());
    //for( uint i = 0; i < vReportVectors.size(); i++)
    //  vReportVectors[i]->Debug( hFile);
    };


  private:
  std::vector< DRS_ReportVectorTree *> vReportVectors;

  auto_ptr<DRS_FieldData> pFieldData;
};


class DRS_ReportTree : public DRS_Tree<DRS_ReportNode, DRS_ReportDim>
{
  public:
  DRS_ReportTree( DRS_Application const &rAppl, DRS_Descriptor const &rDescriptor);
  ~DRS_ReportTree() {};

  //Report generation
  void AddSubreport( uint iSearchFieldID);
  void AddVector( uint iVectorID, uint32 *pVectorSelector);
  void Report( AT_Record_List const *pRecordList, bool *pIsCancel);

  //Report retrieval

  private:
  DRS_Application const &oAppl;

  auto_array<auto_ptr<uint32> >    addrSelectors;   //addrSelector for each vector.
  std::vector<uint>               vSearchFieldIDs;

  DRS_DescriptorSerialize         descr;
};



class DRS_ReportVectorTreeNode : public DRS_TreeNodeMapped<DRS_ReportVectorTreeNode>
{
  public:
  //Constructor
  DRS_ReportVectorTreeNode() : DRS_TreeNodeMapped<DRS_ReportVectorTreeNode>(), last_address(0), has_data(false) {};
  DRS_ReportVectorTreeNode( uint32 iID)
      : DRS_TreeNodeMapped<DRS_ReportVectorTreeNode>( iID), last_address(0), has_data(false)
    {};

  //Copy constructor
  DRS_ReportVectorTreeNode( DRS_ReportVectorTreeNode const &rNode, DRS_Vector const &rVector);

  //INVESTIGATE!!!!
  //throws here!!!!! When isMapped to child is false and child dim is collective!!!!
  DRS_ReportVectorTreeNode( DRS_ReportVectorTreeNode const &rNode) { throw AT_Unexpected_Err;};

  //Report generation
  void                              LoadData( uint32 *addrVector, DRS_VectorDim const *pDim, DRS_VectorData const &rData, bool hasData);

  DRS_VectorData const * 		      VectorData() const { return apVectorData.get(); };
  virtual void 							GetData( DRS_VectorDataElem *pVector[]) const { (*apVectorData).GetData( pVector);};

  void operator += (DRS_ReportVectorTreeNode const &rNewNode);
  void addTreeNode (DRS_ReportVectorTreeNode const &rNewNode);

  void Debug( FILE *hFile)
    const
    {
    };
  bool hasData() const { return has_data; }

protected:
  auto_ptr<DRS_VectorData> apVectorData;
  uint last_address;
  bool has_data;
};

class DRS_ReportVectorTree : public DRS_Tree<DRS_ReportVectorTreeNode, DRS_VectorDim>
{
  public:
  //Explicit
  DRS_ReportVectorTree( DRS_Vector const &rRefVector, uint32 const *pSelector);
  //Copy constructor
  DRS_ReportVectorTree( DRS_ReportVectorTree const &rReportVector);

  void SelectorGet( uint32 * addrSelector) const;

  inline DRS_Vector const & Vector() const { return rVector; };
  void                      operator<< ( DRS_RecordSet &rRecord);
  void                      operator+= (const DRS_ReportVectorTree &rNewVector);
  void                      addTree (DRS_ReportVectorTree const &rNewVector);

  void Debug( FILE *hFile)
    const
    {
    fprintf( hFile, "Report vector for Vector%u\n", rVector.VectorID());
    GetRootNode()->Debug( hFile);
    };

  private:
  DRS_Vector const & rVector;
  uint32 const * addrSelector;
};


class DRS_ReportVectorTreeSumNode : public DRS_ReportVectorTreeNode
{
  public:
  DRS_ReportVectorTreeSumNode() : DRS_ReportVectorTreeNode( REPORTVECTORSUMNODE_ID)
    {};
  DRS_ReportVectorTreeSumNode(uint iID) : DRS_ReportVectorTreeNode( iID)
    {};
  //Copy constructor
  DRS_ReportVectorTreeSumNode( DRS_ReportVectorTreeSumNode const &rCopy) : DRS_ReportVectorTreeNode( rCopy)
    {};

  //void        AddVectorAddress( uint32 *pVectorIDs, DRS_VectorDim const *pDim, DRS_Vector const &rVector);
  void        LoadRecord( DRS_RecordSet &rRecord, uint32 *addrVector, DRS_Vector const & rVector, DRS_VectorDim const *pDim);


};


#endif
