
#include <QtCore/QString.h>
#include <QtCore/QTextStream.h>

#include "x_at_data.h"
#include "x_at_error.h"
#include "data/store/tablecursor.h"

AT_Database::AT_Database
  (AT_Read_Rand_File *descFile,      
   AT_Read_Rand_File *refFile,       
   AT_Read_Rand_File *dataFile) :    
   x_Table(0)
{
  this->AT_Database::AT_Database(descFile->fullName(), refFile->fullName(), dataFile->fullName());
}

AT_Database::AT_Database
 (AT_String descFileName, 
  AT_String refFileName, 
  AT_String dataFileName)
{
  QString c;
  QTextStream(&c) << "<store"
                  << " dt=\"" << descFileName << "\"" 
                  << " di=\"" << refFileName << "\"" 
                  << " dd=\"" << dataFileName << "\"/>";

  try
  {
    x_Table = new Xpace::TableCursor(Xpace::Configuration(c));

    for (uint i(0); i < x_Table->getColumnCount(); ++i)
    {
      bool is_text(x_Table->getColumnConfig(i).getValue("type") == "string");
      field_descs.push_back(fieldDesc(is_text));
    }
  }

  catch (Xpace::Exception& ex)
  {
    throw AT_Xpace_Err(ex);
  }
}

AT_Database::AT_Database
  (const AT_Database& rhs) :
    x_Table(new Xpace::TableCursor(*rhs.x_Table)),
    field_descs(rhs.field_descs)
{
}

AT_Database& AT_Database::operator=
  (const AT_Database& rhs)
{
  x_Table = new Xpace::TableCursor(*rhs.x_Table);
  field_descs = rhs.field_descs;
  return *this;
}

AT_Database::~AT_Database
  ()
{
  delete x_Table;
}

uint32 AT_Database::getRecordCount
  ()
  const
{
  return x_Table->getRowCount();
}

uint AT_Database::getFieldCount
  ()
  const
{
  return x_Table->getColumnCount();
}

const AT_Record* AT_Database::getRecord
  (uint32 recNum)
  const
{
  return x_Table->moveToRow(recNum) ? new AT_Record(x_Table, this, recNum) : 0;
}

bool AT_Database::readRecord
  (AT_Record* rec,
   uint32 recNum)
  const
{
  Xpace::TableCursor* r(new Xpace::TableCursor(*x_Table));
  if (r->moveToRow(recNum))
  {
    new (rec) AT_Record(r, this, recNum);
    return true;
  }
  delete r;
  return false;
}

const fieldDesc *const AT_Database::getField
  (uint i)
  const
{
  return &field_descs[i];
}

// ================================== AT_RECORD ===============

AT_Record::AT_Record
  (const AT_Record& rhs) :
    x_Table(new Xpace::TableCursor(*rhs.x_Table)),
    database(rhs.database),
    rec_num(rhs.rec_num),
    field_buf(rhs.field_buf)
{
}

AT_Record& AT_Record::operator=
  (const AT_Record& rhs)
{
  x_Table = new Xpace::TableCursor(*rhs.x_Table);
  database = rhs.database;
  rec_num = rhs.rec_num;
  field_buf = rhs.field_buf;
  return *this;
}

AT_Record::~AT_Record
  ()
{
}

uint AT_Record::getOccurCount
  (uint fieldNum)
  const
{
  return 1; 
}

uint AT_Record::getFieldLength
  (uint fieldNum)
  const
{
  return x_Table->getCellRef(fieldNum).length;
}

const byte *const AT_Record::getField
  (uint fieldNum,
   uint occur,
   AT_Num *value)
  const
{
  if (database->getField(fieldNum)->isText())
  {
    Xpace::BytesRef ref(x_Table->getCellRef(fieldNum));
    field_buf.resize(ref.length + 1);
    memcpy(&field_buf[0], ref.data, ref.length);
    field_buf[ref.length] = 0;
    return &field_buf[0];
  }
  
  uint64 val = x_Table->getCellInt(fieldNum);
  field_buf.resize(22);
  _i64toa_s(val, (char*) &field_buf[0], 22, 10);

  if (value)
    *value = val;
  return &field_buf[0];
}