// Change Histroy
// 03/18/04 AV Development: Add VirtualPeriodCount, VirtualPeriod, VirtualIndexPeriod
// 11/20/03 AV Development: BC6 conversion. Overload const ParentDatabase
// 11/19/03 AV Development: Merging Production version 16
// 8/29/03 AV Production: Add GetDatabaseVectorAddress func. Used in AT_QC

#ifndef _DRS_VECT_H_
#define _DRS_VECT_H_

#include <vector>
#include <math.h>

#include "base/at_defs.h"
#include "xdart/x_at_data.h"

#include "drs/drs_appl.h"
#include "drs/drs_type.h"
#include "drs/drs_rec.h"
#include "drs/drs_tree.h"

////////////////////////////////////////////////////////
// DRS_Vector classes
////////////////////////////////////////////////////////

#define NODE_SUM ((uint) -1L)

class APPL_DECL DRS_Vector;
class DRS_RecordSet;

class DRS_VectorQuantile
{
  public:
  DRS_VectorQuantile( byte *sFile, byte *sSection, DRS_Setting BaseKey);

  inline uint                   State() const { return iState;};
  inline DRS_Descriptor const & Descriptor() const {return Descr;};
  inline uint                   Precision() const { return precision; };
  
  private:
  uint iState;
  DRS_DescriptorSerialize Descr;
  uint precision;
};

////////////////////////////////////////////////////////
// Index States
////////////////////////////////////////////////////////
class DRS_VectorIndexState
{
  public:
  DRS_VectorIndexState() : iNormal(0)
    {};
  DRS_VectorIndexState( DRS_FilePath sFile, DRS_FileSetting sSection, DRS_Setting BaseSetting);

  inline uint                   Normal() const { return iNormal;};
  inline DRS_Descriptor const & Descriptor() const { return Descr;};

  private:
  DRS_DescriptorSerialize Descr;
  uint           iNormal;    // Vector indexes are integer indexes with normal
};
////////////////////////////////////////////////////////
// Virtual Periods
////////////////////////////////////////////////////////

//class DRS_Vector;

class DRS_VirtualPeriodDef
{
  public:
  void             		Extract( byte *s);
  inline uint           Offset() const { return v_offset;};
  inline uint           Length() const { return v_len;};

  private:
  uint           			v_offset;
  uint           			v_len;
};

class DRS_VirtualPeriod
{
public:
  DRS_DescriptorSerialize   Descriptor;
  DRS_VirtualPeriodDef      PeriodDef;
};


////////////////////////////////////////////////////////
// Vector Dims
////////////////////////////////////////////////////////
class DRS_VectorNode;
class DRS_Application;
class DRS_VectorData;

class APPL_DECL DRS_VectorDim : public DRS_TreeDim<DRS_VectorDim>
{
  friend DRS_VectorNode;

  public:
  DRS_VectorDim( DRS_Database const &oDatabase, byte *sSectionTag, uint iID, byte *sFile);
  DRS_VectorDim( DRS_VectorDim const &r);

  inline bool IsCollective() const { return isCollective;};
  inline bool IsConstant() const { return isConstant;};
  inline bool IsMappedToChild() const { return isMappedToChild;};
  inline uint32 MappedToChild() const { return lMappedToChild;};
  DRS_Descriptor const & NodeDescr( DRS_Vector const &rVector, uint i) const;
                              //Called for const dims or for total in collective dims.

  void              GetData(  DRS_Vector const &rVector,
                              VectorAddress addrSelector[],
                              VectorAddress addrVector[],
                              AT_Record const *pRecord,
                              DRS_VectorData *pDestVector,
                              bool *pIsAvail = 0 ) const;

  void              BumpDim( DRS_Vector const &rVector, VectorAddress addrVector[]) const;
  void              UnbumpDim( DRS_Vector const &rVector, VectorAddress addrVector[]) const;

  private:
  void              NextDim( DRS_Vector const &rVector,
                              VectorAddress addrSelector[],
                              VectorAddress addrVector[],
                              AT_Record const *pRecord,
                              DRS_VectorData* pDestVector,
                              bool *pIsAvail ) const;


  bool                       isMappedToChild;
  int32                      lMappedToChild;    //Dimension data mapped to rel element
  bool                       isConstant;
  bool                       isCollective;      //Dimension is collective or disparate

  auto_ptr<DRS_DescriptorSerialize>   pTotalDescr;       //Read only for collective dims.

  auto_array<DRS_DescriptorSerialize> aaConstDescr;      //Const dims store const elems.
};

////////////////////////////////////////////////////////
// Vector Node
////////////////////////////////////////////////////////

class APPL_DECL DRS_VectorNode : public DRS_TreeNode<DRS_VectorNode>
{
  friend class DRS_VectorNodeReader;
  typedef DRS_TreeNode<DRS_VectorNode> inherited;

  public:
  DRS_VectorNode() : isInTotal( true)
    {};
  DRS_VectorNode( DRS_VectorNode const &rCopy)
    : Descr( rCopy.Descriptor()), isInTotal( rCopy.IsInTotal())
    {};

  virtual uint32 AssertChild( uint32 lIndex) const;

  uint32 							  GetVectorCount( DRS_VectorDim const *pVectorDim, uint32 *pVectorIDs) const;
  void 								  GetData(  AT_Record const *pRecord, DRS_Vector const *pVector, DRS_VectorDim const *pVectorDim, uint32 pVectorIDs[], DRS_VectorData *pDestVector) const;
  inline DRS_Descriptor const & Descriptor() const {return Descr;};
  inline bool                   IsInTotal() const { return isInTotal;};

  private:
  DRS_DescriptorSerialize Descr;
  bool           isInTotal; //Omit node from calculations?
};

class DRS_VectorNodeReader : public DRS_VectorNode
{
  public:
  DRS_VectorNodeReader( FILE * hFile);
  inline uint Dim() { return iDim;};
  inline bool operator !() const { return !bytesIn;}; 

  private:
  uint iDim;
  uint bytesIn;
};

////////////////////////////////////////////////////////
// DRS_Vector
////////////////////////////////////////////////////////
class DRS_Formula;

//A DRS_Vector is actually a DRS_Tree of Objects, thise objects being of type long[],
//hence vector<long>, but not really here, since they are retrieved as an array.
//We extend this to true vectors by providing "virtual periods" added by the author and
//eventually by the user.

//Each dimension's data may be:
//		mapped to a specific child's data
//		summed from its children's
//		retrieved from a data record.
//		generated from records.

//In the case of DRS_DataVectors, each node retrieves it's data from it's children, mapped or summed,
//except the last dimension, which are record retrievers.

//In the case of DRS_Reports, the nodes sum the data from its children,
//except the last dimension, which are generators.

//In GeoDart, the DRS_Reports are all record retrievers.


class APPL_DECL DRS_Vector : public DRS_Tree<DRS_VectorNode, DRS_VectorDim>
{
  friend class DRS_VectorData;

  public:
  DRS_Vector( uint iVectorID, DRS_Database const &rParent, byte *sFile);
  ~DRS_Vector();

  inline
  DRS_Descriptor const &  Descriptor() const
                                    {AT_Assert( GetRootNode(), *this, "RootNode");
                                     return GetRootNode()->Descriptor();
                                    };

  DRS_Descriptor const &  NodeDescr( uint32 *addrNode, uint iDepth) const;
  uint                    NodeCount( uint iDepth, VectorAddress *addrVector, bool isIncludeTotal = false) const;
  void                    NodeOccurrences( DRS_RecordSet *pRecord,
                                           uint32 addr[],
                                           uint16 iDepth,
                                           bool isUnique,
                                           std::vector<uint> *pOccs) const;

                          //Get vector address for ordinal vector number
  void                    GetVectorAddress( DRS_RecordSet & oRecord, uint iRecordVector, uint32 *addrVector) const;
                          //Fill vector with ordinal vector occurrences for this address.
  void                    VectorOccurrences( DRS_RecordSet & oRecordSet,
                                             std::vector<uint> * pvOccs,
                                             VectorAddress const addrVector[]) const;

  inline uint    	  PeriodCount( void) const { return(iPeriodCount + iVirtualPeriodCount);};
  inline uint    	  VirtualPeriodCount( void) const { return(iVirtualPeriodCount);};
  inline uint    	  IndexPeriodCount( void) const
                                     { return( iIndexPeriodCount ? iIndexPeriodCount : PeriodCount());};
  inline uint    	  VirtualIndexPeriodCount( void) const
                                     { return( iIndexPeriodCount ? iVIndexPeriodCount : VirtualPeriodCount());};

         uint             IndexPeriodToDataPeriod( uint iIndexPeriod) const;
         uint             DataPeriodToIndexPeriod( uint iDataPeriod) const;

  DRS_Descriptor const &  Period( uint iPeriod) const;
  DRS_Descriptor const &  IndexPeriod( uint iPeriod) const;

  DRS_Descriptor const &  VirtualPeriod( uint iPeriod) const;
  DRS_Descriptor const &  VirtualIndexPeriod( uint iPeriod) const;

  //NOTE: User requests for state include Quantiles.
  //Assumed that all quantiles are indexed.
  inline uint    	  IndexStateCount(void) const { return(iIndexStateCount + iQuantileCount);};
  DRS_Descriptor const &  IndexStateDescr( uint iState) const;

  inline uint    						FormulaCount( void) const { return(iFormulaCount);};
  DRS_Formula const &     Formula( uint iFormula) const;

  void                    GetData( AT_Record const *pRecord,
                                          uint32 pVectorIDs[], DRS_VectorData *pDestVector, bool *pIsAvail = 0) const;
  void                    GetData( DRS_RecordSet *pRecord,
                                          uint32 pVectorIDs[], DRS_VectorData *pDestVector, bool *pIsAvail = 0) const;
  void                    GetData( DRS_RecordSet *pRecord, uint iOccurrence, DRS_VectorData *pDest) const;


  inline uint             VectorID() const { return iVectorID; };
  inline
  DRS_Database const &    ParentDatabase() const { return rDatabase;}
  DRS_Database       &    ParentDatabase()       { return (DRS_Database &)rDatabase;}

  inline uint    					DataPrecision( void) const { return m_iDataPrecision;};
  inline uint    					DataPrecisionMult( void) const { return pow10<uint>(m_iDataPrecision);};
  inline uint    					IndexPrecision( void) const { return m_iIndexPrecision;};
  inline uint    					IndexPrecisionMult( void) const { return pow10<uint>(m_iIndexPrecision);};

  /* IndexFiles and IDs
  A vector has a single or multiple index files based on its IndexFileMapLevel.
  The vector stores its base IndexFileID, read from file.
  */
  uint                    IndexFileCount() const;
  inline int              IndexFileIDBase() const { return iIndexFileIDBase;};
  uint                    IndexCount() const;

  DRS_Index *             IndexOpen( uint32 VectorAddress[], uint iVectorState, uint iPeriod, uint prefPrec) const;

                             //FormulaNodeObjectVectorQuantile.
  uint                       QunatileCount() const { return iQuantileCount; };
  DRS_VectorQuantile const & VectorQuantile( uint iQuantileID) const;

  uint32                * GetDatabaseVectorAddress() const { return lDatabaseVectorAddress.get(); }
                          //TODO: Should be protected. Public for VectorQualtiles
  const uint32          * IndexAddress(uint32 VectorAddress[]) const;
  uint                    IndexID( const uint32 VectorAddress[], uint iState, uint iPeriod) const;
  int                     IndexFileID( const uint32 VectorAddress[]) const;
  uint                    Normal(uint state) const;

  uint                    GetDataSize() const;
  uint                    GetDataTextSize() const;

private:
  inline void                    SetVectorIds( uint32 *IDs, const uint32 *addrVector) const;

  DRS_Database const &  rDatabase;
  uint           	iVectorID;     //VectorID in database. Based on order in file.

  //Mapping of DRS_Vector to Database vector
  auto_array<uint32>    lDatabaseVectorAddress; //array
  uint                  iDatabaseVectorDepth;

  int                   iIndexFileIDBase;    //Base index file id
  int                   iIndexListMapLevel;  //Level within vector to which indexLists are mapped.

  uint           			iPeriodCount;   //AT_Database::
  DRS_DescriptorSerialize	*Periods;

  uint              		iVirtualPeriodCount;
  DRS_VirtualPeriod 		*VirtualPeriods;

  uint                  iIndexPeriodCount;
  uint                  iVIndexPeriodCount;
  uint                  *pIndexPeriods;    //Integer array of data period offsets that are indexed

  //Vector data precision. Defined as a number of digits after decimal point
  uint                  m_iDataPrecision;
  //Vector index precision. Defined as a number of digits after decimal point
  uint                  m_iIndexPrecision;

  //A vector presents States as the total of states and quantiles.
  uint                                         iIndexStateCount;
  auto_array< auto_ptr<DRS_VectorIndexState> > aaIndexStates;

  uint                                         iQuantileCount;
  auto_array< auto_ptr<DRS_VectorQuantile> >   aaQuantiles;

  //Vector formulas, e.g. (Quantity, Share, etc.)
  uint           			                       iFormulaCount;

  // AV auto_array does not work !!!
  //auto_array< auto_ptr<DRS_Formula> >          aaFormulas;  //auto_array of auto_ptrs
  DRS_Formula                                **aaFormulas;
};


#endif
