// Change History
// 01/03/03 AV Development: Add CreateVector function
// 01/03/03 AV Development: Use AT_Num64 for result values
// 01/03/03 AV Development: BC6 conversion. const/none const
// 11/19/03 AV Development: Merge Production version 9
// 10/29/03 AV Production: 64 bit conversion

#ifndef DRS_DATA_H_
#define DRS_DATA_H_

#include "drs_vect.h"

#define TEXT_DATA_SIZE  10

class DRS_RecordSet;
class DRS_FormulaNode;

typedef double RealValue;

// **************************************************************************
// DRS_VectorDataElem declaration
// **************************************************************************
class DRS_VectorDataElem
{
  public:
  //Constructors
  DRS_VectorDataElem() : m_iValue(0), m_iMaxPrecisionMult(1) { memset( &m_FRValue, 0, sizeof( FormulaResult));};
  DRS_VectorDataElem( AT_Num64 iValue, uint iMaxPrecisionMult) : m_iValue(iValue),
                                                             m_iMaxPrecisionMult( iMaxPrecisionMult)
                                                             { memset( &m_FRValue, 0, sizeof( FormulaResult));};

  //Copy
  DRS_VectorDataElem( DRS_VectorDataElem const &rFormulaResult);

  //reset
  DRS_VectorDataElem &ResetDataElem( AT_Num64 iValue, uint iMaxPrecisionMult);

  //Assignemnt Operator
  DRS_VectorDataElem & operator= ( const DRS_VectorDataElem &rhs);

  //Math Operators
  DRS_VectorDataElem operator+ ( const DRS_VectorDataElem &rhs) const;
  DRS_VectorDataElem operator- ( const DRS_VectorDataElem &rhs) const;
  DRS_VectorDataElem operator* ( const DRS_VectorDataElem &rhs) const;
  DRS_VectorDataElem operator/ ( const DRS_VectorDataElem &rhs) const;

  //Evaluation operators
  bool operator !() const;

  //Formula results
  void SetFormulaNode( const DRS_FormulaNode *pParentFormula,
                       const DRS_VectorData *pParentData,
                       uint iParentItem,
                       uint32 lRecordNum);
  void ResetFormulaNode() { m_FRValue.pFormulaNode = NULL;};

  uint GetPrecisionMult() const { return m_iMaxPrecisionMult;};
  //Access Value
  AT_Num64 GetRawValue() const;
  AT_Num64 GetIntValue() const;
  RealValue GetRealValue() const;
  RealValue GetRealValueAtPrecision( uint iPrecision ) const;

  static uint GetSize() { DRS_VectorDataElem e;
    return sizeof(e.m_iValue); }

  private:
  //Result Value
  AT_Num64 m_iValue;

  //Precision. Num of digits after decimal point
  uint m_iMaxPrecisionMult;

  //Lasy fomula calculation
  struct FormulaResult
    {
    uint iItem;
    const DRS_VectorData *pVectorData;
    uint32 lRecNum;
    const DRS_FormulaNode *pFormulaNode;

    FormulaResult & operator = ( const FormulaResult &rhs)
      {
      iItem = rhs.iItem;
      pVectorData = rhs.pVectorData;
      lRecNum = rhs.lRecNum;
      pFormulaNode = rhs.pFormulaNode;

      return *this;
      };
    DRS_VectorDataElem Compute( uint *piPresMult) const;
    };
  FormulaResult m_FRValue;
};

// **************************************************************************
// DRS_VectorData declaration
// **************************************************************************
class DRS_VectorData
{
  friend DRS_VectorData;

  public:
  //Constructors
  DRS_VectorData() : m_pData(0), m_pVector(NULL) {};
  DRS_VectorData( DRS_Vector const &rVector);
  //Create from record
  DRS_VectorData( DRS_RecordSet &rRecord, const DRS_Vector &rVector, uint iOccurrence);

  //Copy
  DRS_VectorData( const DRS_VectorData &rDataVector);

  inline ~DRS_VectorData() { delete [] m_pData;};

  inline const DRS_Vector* GetVector() const { return m_pVector; };

  DRS_VectorData const & operator+= ( const DRS_VectorData &rhs);
  DRS_VectorData const & operator= ( const DRS_VectorData &rhs);

  inline void Clear() { memset( m_pData, 0, m_pVector->iPeriodCount * sizeof(AT_Num)); };

  inline DRS_VectorDataElem &GetDataElement( uint iElem) const;
  void GetData( DRS_VectorDataElem* pVectorElems[]) const;

  bool LoadFromATVector( const AT_Record *pRecord, uint32 *ids);
  bool LoadFromATVector( const AT_Record *pRecord, uint32 iOccurrence);
  inline bool LoadFromATVector( DRS_RecordSet &rRecordSet, uint32 *ids)
         { return LoadFromATVector( rRecordSet.Record( m_pVector->rDatabase.ID()), ids);};
  inline bool LoadFromATVector( DRS_RecordSet &rRecordSet, uint32 iOccurrence)
         { return LoadFromATVector( rRecordSet.Record( m_pVector->rDatabase.ID()), iOccurrence);};
  bool LoadFromDRSVector( DRS_RecordSet &rRecordSet, uint32 *ids);
  static uint GetDataSize() { return sizeof(AT_Num); }
  static uint GetDataTextSize() { return TEXT_DATA_SIZE; }  

  private:
  inline void CopyData(AT_Num * src);
  inline void CreateVector();

  AT_Num *m_pData;
  const DRS_Vector *m_pVector;
  mutable DRS_VectorDataElem m_elem;

};

// **************************************************************************
// DRS_FieldData declaration
// **************************************************************************
class DRS_FieldData
{
  friend DRS_FieldData;

  public:
  //Constructors
  //DRS_FieldData() : rField(0), iFieldID( (uint) -1), buf(0), buflen(0), datalen(0) {};
  DRS_FieldData( DRS_Field const &rFieldIn) : pDataField( & rFieldIn), buf(0), buflen(0), datalen(0) {};
  //Copy Constructor
  DRS_FieldData( DRS_FieldData const &rCopy);

  inline ~DRS_FieldData() {delete [] buf;};

  inline DRS_Field const & DataField() const
          { return *pDataField;}

  DRS_FieldData const & operator=( DRS_FieldData const &rCopy);
  void operator<< ( DRS_RecordSet &rRec);
  inline bool operator== ( DRS_FieldData const &rComp) const
    {
    return( datalen == rComp.datalen ?
                 !memcmp( buf, rComp.buf, datalen) :
                 false);
    };

  inline uint Length() const { return datalen;};
  void Get( byte *sDest, uint iLen) const;

  private:
  DRS_Field const *pDataField;
  uint iFieldID;
  byte * buf;
  uint buflen;
  uint datalen;
};

#endif