// Change History
// 11/19/03 AV Development: Merge Production version 9
// 10/29/03 AV Production: 64 bit conversion
// 10/29/03 AV Production: Merge development version 12 (Add MaxSize, and MaxOccurs.)
// 8/20/03 AV Development: Fix sign/unsign warnings
// 8/20/03 AV Development: Fix sign/unsign warnings

//
// AT_DATA.H -- access to vector and scalar data
//
// To get at stored, compressed data, first open (construct) an AT_Database.
// From an AT_Database, an AT_Record is available by record number.
// From an AT_Record, both scalar fields and vector data can be retrieved.
// Access to fields is by field number; access to vectors is by vector number
// within a record, or vector ID (e.g. market, product) and type (e.g. new/total).
//

#ifndef AT_DATA_H
#define AT_DATA_H

#include "at_defs.h"
#include "x_at_file.h"

#include "data/store/tablecursor.h"

class SEARCH_DECL fieldDesc
{
public :
  fieldDesc
    () :
      is_text(true)
  {};

  fieldDesc
    (bool isText) :
      is_text(isText)
  {};

  fieldDesc& operator=
    (const fieldDesc& rhs)
  { 
    is_text = rhs.is_text; 
    return *this;
  };

  void read
    (AT_File *f)
  {};

  // decompress field occurrence
  uint decode
    (/*AT_Get_Int_List*/ void *compField,
     byte *buf,
     uint bufLen,
     AT_Num *fieldVal,  // if numeric
     uint *occurs,
     uint *sameAs,
     byte occurSeparator = ' ')
    const
  { assert(0); return 0; };

  bool isText
    ()
    const
  { return is_text; };

  // PS these need to work for real...
  bool combineOccurs
    ()
    const
  { return false; };
  uint getMaxSize
    ()
    const
  { return 255; }
  uint getMaxOccurs
    ()
    const
  { return 1; }

private :
  bool is_text;
};

class SEARCH_DECL AT_Record;

// ================================== AT_DATABASE =============

namespace Xpace
{
  class RowColumn_Cursor;
};

class SEARCH_DECL AT_Database
{
public :
  AT_Database
    (AT_Read_Rand_File *descFile,      // descriptor file (cf. applDT00.)
     AT_Read_Rand_File *refFile,       // reference file (cf. applDI00.)
     AT_Read_Rand_File *dataFile);     // content file (cf. applDD00.)

  AT_Database
    (AT_String descFileName,
     AT_String refFileName,
     AT_String dataFileName);

  AT_Database
    (const AT_Database&);
  AT_Database& operator=
    (const AT_Database&);

  ~AT_Database
    ();

  // is database (in)valid?
  virtual bool operator!
    ()
    const
  { return !x_Table; };

  // how many records in database
  virtual uint32 getRecordCount
    ()
    const;

  // how many scalar fields
  virtual uint getFieldCount
    ()
    const;

  // maximum size of one record's scalar part
  virtual uint32 getMaxSize
    ()
    const
  { assert(0); return 0; };

  // how many vector IDs (e.g. market, product)
  virtual uint getVectorIDs
    ()
    const
  { assert(0); return 0; };

  // for compatibility
  virtual uint getVectorTypes
    ()
    const
  { assert(0); return 0; };

  // vect is forced to have this many children
  virtual uint getImplicitVects
    (uint16 *IDs = 0,
     uint16 IDCount = 0)
    const
  { assert(0); return 0; };

  // how many periods per vector
  virtual uint getPeriods
    ()
    const
  { assert(0); return 0; };

  // construct a record
  virtual const AT_Record* getRecord
    (uint32 recNum)
    const;

  // read a record
  virtual bool readRecord
    (AT_Record* rec,
     uint32 recNum)
    const;

  // scalar field desc
  const fieldDesc *const getField
    (uint i)
    const;

  uint getVersion
    ()
    const
  { return 0; }
  
  Xpace::TableCursor* x_Table;
  AT_Database
    (Xpace::TableCursor* tc) :
      x_Table(tc)
  {};

  std::vector<fieldDesc> field_descs;
};

// ================================== AT_RECORD ===============

class SEARCH_DECL AT_Record
{
public :
  uint32 getRecordNumber
    ()
    const
  { return rec_num; };

  // returns scalar field's occur count
  uint getOccurCount
    (uint fieldNum)
    const;

  //returns scalar field's length
  uint getFieldLength
    (uint fieldNum)
    const;

  // returns scalar field; fills in value if numeric
  // don't delete ptr!
  const byte *const getField
    (uint fieldNum,
     uint occur = 0,
     AT_Num *value = 0)
    const;

  // number of vectors in this record
  uint32 getVectorCount
    ()
    const
  { 
    assert(0);
    return 0;
  };
  // get vector by number
  bool getVector
    (AT_Num *vector,    // result
     uint32 *IDs,       // result
     uint32 vectNum)
    const
  {
    assert(0);
    return false;
  };
  const AT_Num* getVector
    (uint32 vectNum)
    const
  { 
    assert(0);
    return 0;
  };
  const uint16* getAddress
    (uint32 vectNum)
    const
  { 
    assert(0);
    return 0;
  };
  // get vector by IDs
  bool getVector
    (AT_Num *vector,    // result
     uint32 *IDs)
    const
  { 
    assert(0);
    return 0;
  };
  // get list of vectors that match IDs; return number of vector numbers filled in
  uint getVectorList
    (uint* list,     // result (vector numbers)
     uint  start,    // start at this position
     uint  count,    // fill in this many
     uint* IDs)      // MAXUINT = don't care
    const
  { 
    assert(0);
    return 0;
  };

  // --------------------------------

  AT_Record
    (const Xpace::TableCursor* tc,
     const AT_Database* db,
     uint recNum) :
      x_Table(tc),
      database(db),
      rec_num(recNum)
  {};
  AT_Record
    (const AT_Record&);
  AT_Record& operator=
    (const AT_Record&);
  ~AT_Record
    ();

private :
  const Xpace::TableCursor* x_Table;
  const AT_Database* database;
  uint rec_num;
  mutable std::vector<byte> field_buf;
};

#endif