#include "TblFileObj.h"
#include <iostream.h>


int CompareTablesTrivial(ISTable * a, ISTable * b);
int CompareStringArrays(ReVarCifArray<CifString> * a, ReVarCifArray<CifString> * b);
void FillTestTable(ISTable *s, int nrows, int ncols, const char *fillPattern);


int main() {

  ISTable * s=NULL, *t = NULL;

  CifString tableLabel, blockLabel;
  //    int i,j, nblocks=5, ntables=100, nRows=100, nCols=10;
    int i,j, nblocks=2, ntables=2, nRows=10, nCols=10;

  
  //
  //  Create a test file 
  //
  TblFileObj * fobjR = new TblFileObj((char*)"./test/TESTFILE1", WRITE_MODE);
  for (j=0; j < nblocks; j++) {
    blockLabel.Clear();
    blockLabel.Copy("Block-");
    blockLabel += j;
    fobjR->SetDataBlock(blockLabel.Text());
    for (i=0; i < ntables; i++) {
      tableLabel.Clear();
      tableLabel.Copy("Table-");
      tableLabel += i;
      s = new ISTable(tableLabel.Text());
      FillTestTable(s, nRows, nCols, "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345689");
      fobjR->WriteTable(s,blockLabel.Text(),tableLabel.Text());
      // ierr = fobjR->WriteTable(s,blockLabel.Text(),tableLabel.Text());
      //      cerr << " i " << i << " j " << j << " error " << ierr << endl;
    }
  }
  //  s=fobjR->GetTablePtr(blockLabel.Text(),tableLabel.Text());
  //  s->PrintTable();
  //  cerr << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
  //  cerr << "PrintHeaderInfo() - Write Test I - Before CloseFile()" << endl;
  //  fobjR->PrintHeaderInfo();

  fobjR->CloseFile(1);
  if (fobjR) delete fobjR;

  cerr << "Passed - Write Test I" << endl;



  //
  // Read and check the test file (Pass I)
  //

  fobjR = new TblFileObj((char*)"./test/TESTFILE1", READ_MODE);
  t = fobjR->GetTablePtr("Block-1","Table-1");
  if ((t->GetNumRows() != nRows) || (t->GetNumColumns() != nCols)) 
    cerr << "Table size corupted " << " rows " << t->GetNumRows() << " columns " 
	 << t->GetNumColumns() << endl;
  
  for (j=0; j < nblocks; j++) {
    blockLabel.Clear();
    blockLabel.Copy("Block-");
    blockLabel += j;
    fobjR->SetDataBlock(blockLabel.Text());
    for (i=0; i < ntables; i++) {
      tableLabel.Clear();
      tableLabel.Copy("Table-");
      tableLabel += i;
      s = fobjR->GetTablePtr(blockLabel.Text(),tableLabel.Text());
      CompareTablesTrivial(s,t) ;
    }
  }
  fobjR->CloseFile(0);
  if (fobjR) delete fobjR;
  cerr << "Passed - Read Test I" << endl;

  //
  // Read and check the test file (Pass II)
  //


  fobjR = new TblFileObj((char*)"./test/TESTFILE1", READ_MODE);
  t = fobjR->GetTablePtr("Block-1","Table-1");
  if ((t->GetNumRows() != nRows) || (t->GetNumColumns() != nCols)) 
    cerr << "Table size corupted " << " rows " << t->GetNumRows() << " columns " 
	 << t->GetNumColumns() << endl;
  
  for (j=0; j < nblocks; j++) {
    blockLabel.Clear();
    blockLabel.Copy("Block-");
    blockLabel += j;
    fobjR->SetDataBlock(blockLabel.Text());
    for (i=0; i < ntables; i++) {
      tableLabel.Clear();
      tableLabel.Copy("Table-");
      tableLabel += i;
      s = fobjR->GetTablePtr(blockLabel.Text(),tableLabel.Text());
      CompareTablesTrivial(s,t) ;
    }
  }
  fobjR->CloseFile(0);
  if (fobjR) delete fobjR;
  cerr << "Passed - Read Test II" << endl;

  //
  // Read and check the test file in APPEND MODE (Pass I)
  //


  cerr << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
  cerr << "Beginning - Append Mode Test I" << endl;
  fobjR = new TblFileObj((char*)"./test/TESTFILE1", UPDATE_MODE);

  //  cerr << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
  //  cerr << "PrintHeaderInfo() - Append Mode Test I" << endl;
  //  fobjR->PrintHeaderInfo();

  //  cerr << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
  //  cerr << "PrintIndex() - Append Mode Test I" << endl;
  //  fobjR->PrintIndex();

  t = fobjR->GetTablePtr("Block-1","Table-1");
  if ((t->GetNumRows() != nRows) || (t->GetNumColumns() != nCols)) 
    cerr << "Table size corupted " << " rows " << t->GetNumRows() << " columns " << t->GetNumColumns() << endl;
  
  for (j=0; j < nblocks; j++) {
    blockLabel.Clear();
    blockLabel.Copy("Block-");
    blockLabel += j;
    fobjR->SetDataBlock(blockLabel.Text());
    for (i=0; i < ntables; i++) {
      tableLabel.Clear();
      tableLabel.Copy("Table-");
      tableLabel += i;
      s = fobjR->GetTablePtr(blockLabel.Text(),tableLabel.Text());
      CompareTablesTrivial(s,t) ;
    }
  }

  fobjR->CloseFile(0);
  if (fobjR) delete fobjR;

  cerr << "Completed - Append Mode Test I" << endl;
  cerr << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;

  //
  // Read and check the test file in APPEND MODE (Pass II)
  //
  cerr << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
  cerr << "Beginning - Append Mode Test II" << endl;
  fobjR = new TblFileObj((char*)"./test/TESTFILE1", UPDATE_MODE);

  //  cerr << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
  //  cerr << "PrintHeaderInfo() - Append Mode Test I" << endl;
  //  fobjR->PrintHeaderInfo();

  //  cerr << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
  //  cerr << "PrintIndex() - Append Mode Test II" << endl;
  //  fobjR->PrintIndex();
  //  fobjR->DumpFile();

  t = fobjR->GetTablePtr("Block-1","Table-1");
  if ((t->GetNumRows() != nRows) || (t->GetNumColumns() != nCols)) 
    cerr << "Table size corupted " << " rows " << t->GetNumRows() << " columns " 
	 << t->GetNumColumns() << endl;
  
  for (j=0; j < nblocks; j++) {
    blockLabel.Clear();
    blockLabel.Copy("Block-");
    blockLabel += j;
    fobjR->SetDataBlock(blockLabel.Text());
    for (i=0; i < ntables; i++) {
      tableLabel.Clear();
      tableLabel.Copy("Table-");
      tableLabel += i;
      s = fobjR->GetTablePtr(blockLabel.Text(),tableLabel.Text());
      CompareTablesTrivial(s,t) ;
    }
  }

  fobjR->CloseFile(0);
  if (fobjR) delete fobjR;
  cerr << "Completed - Append Mode Test II" << endl;


  // *************************************************************
  //  Rewrite the test file 
  //
  fobjR = new TblFileObj((char*)"./test/TESTFILE1", UPDATE_MODE);

  cerr << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
  cerr << "Beginning - ReWrite Mode Test I" << endl;

  t = fobjR->GetTablePtr("Block-1","Table-1");
  if ((t->GetNumRows() != nRows) || (t->GetNumColumns() != nCols)) 
    cerr << "Table size corupted " << " rows " << t->GetNumRows() << " columns " 
	 << t->GetNumColumns() << endl;
  
  for (j=0; j < nblocks; j++) {
    blockLabel.Clear();
    blockLabel.Copy("Block-");
    blockLabel += j;
    fobjR->SetDataBlock(blockLabel.Text());
    for (i=0; i < ntables; i++) {
      tableLabel.Clear();
      tableLabel.Copy("Table-");
      tableLabel += i;
      s = fobjR->GetTablePtr(blockLabel.Text(),tableLabel.Text());
      CompareTablesTrivial(s,t) ;
    }
  }
  //
  //

  // This writes over all of the existing tables... UNSAFE... 
  // and ther is a leak because of that
  for (j=0; j < nblocks; j++) {
    blockLabel.Clear();
    blockLabel.Copy("Block-");
    blockLabel += j;
    fobjR->SetDataBlock(blockLabel.Text());
    for (i=0; i < ntables; i++) {
      tableLabel.Clear();
      tableLabel.Copy("Table-");
      tableLabel += i;
      s = new ISTable(tableLabel.Text());
      FillTestTable(s, nRows, nCols, 
		    "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345689");
      fobjR->WriteTable(s,blockLabel.Text(),tableLabel.Text());
//            if (s)  delete s;
    }
  }

#if 0
  // This adds a new set of tables.. 
  //
  for (j=0; j < nblocks; j++) {
    blockLabel.Clear();
    blockLabel.Copy("New-Block-");
    blockLabel += j;
    fobjR->SetDataBlock(blockLabel.Text());
    for (i=0; i < ntables; i++) {
      tableLabel.Clear();
      tableLabel.Copy("New-Table-");
      tableLabel += i;
      s = new ISTable(tableLabel.Text());
      FillTestTable(s, nRows, nCols, 
		    "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345689");
      fobjR->WriteTable(s,blockLabel.Text(),tableLabel.Text());
//            if (s)  delete s;
    }
  }
#endif
  //jdw 
  fobjR->PrintHeaderInfo();
  fobjR->CloseFile(0);
  if (fobjR) delete fobjR;
  cerr << "Passed     - ReWrite Test I" << endl;
  cerr << "Completed - Append Mode Test II" << endl;

  //
  // Read and check the test file in APPEND MODE (Pass III)
  //
  cerr << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
  cerr << "Beginning - Append Mode Test III" << endl;
  fobjR = new TblFileObj((char*)"./test/TESTFILE1", UPDATE_MODE);

  t = fobjR->GetTablePtr("Block-1","Table-1");
  if ((t->GetNumRows() != nRows) || (t->GetNumColumns() != nCols)) 
    cerr << "Table size corupted " << " rows " << t->GetNumRows() << " columns " 
	 << t->GetNumColumns() << endl;
  
  for (j=0; j < nblocks; j++) {
    blockLabel.Clear();
    blockLabel.Copy("Block-");
    blockLabel += j;
    fobjR->SetDataBlock(blockLabel.Text());
    for (i=0; i < ntables; i++) {
      tableLabel.Clear();
      tableLabel.Copy("Table-");
      tableLabel += i;
      s = fobjR->GetTablePtr(blockLabel.Text(),tableLabel.Text());
      CompareTablesTrivial(s,t) ;
    }
  }
#if 0
  t = fobjR->GetTablePtr("New-Block-1","New-Table-1");
  if ((t->GetNumRows() != nRows) || (t->GetNumColumns() != nCols)) 
    cerr << "Table size corupted " << " rows " << t->GetNumRows() << " columns " 
	 << t->GetNumColumns() << endl;
  
  for (j=0; j < nblocks; j++) {
    blockLabel.Clear();
    blockLabel.Copy("New-Block-");
    blockLabel += j;
    fobjR->SetDataBlock(blockLabel.Text());
    for (i=0; i < ntables; i++) {
      tableLabel.Clear();
      tableLabel.Copy("New-Table-");
      tableLabel += i;
      s = fobjR->GetTablePtr(blockLabel.Text(),tableLabel.Text());
      CompareTablesTrivial(s,t) ;
    }
  }
#endif
  fobjR->CloseFile(0);
  if (fobjR) delete fobjR;
  cerr << "Completed - Append Mode Test III" << endl;

  exit(0);
} 

void FillTestTable(ISTable *s, int nrows, int ncols, const char *fillPattern) {
 CifString colLabel, rowData;
 int i,j;

 for (i=0; i < ncols; i++) {
   colLabel.Clear();
   colLabel.Copy("Column-");
   colLabel += i;
   s->AddColumn(colLabel.Text());
 }
 for (j = 0; j < nrows; j++) {
   s->AddRow();
   for (i=0; i < ncols; i++) {
     rowData.Clear();
     rowData.Copy("R-");
     rowData += j;
     rowData += "-C-";
     rowData += i;
     rowData += fillPattern;
     s->AddElementToRow(rowData, j);
   }
 }
}

int CompareTablesTrivial(ISTable * a, ISTable * b) {

  ReVarCifArray<CifString> * a1 = NULL, * b1 = NULL;
  int x1, x2, y1, y2, i,j;

  //  cerr << "Comparing tables " <<  a->GetName() << " and " << b->GetName() << endl;

  x1 = a->GetNumRows();
  x2 = b->GetNumRows();
  if (x1 != x2) {
    cerr << "Tables non-equivalent" << endl;
    cerr << "Comparing tables " <<  a->GetName() << " has row length " << x1 << endl;
    cerr << "Comparing tables " <<  b->GetName() << " has row length " << x2 << endl;
    return -1;
  }

  y1 = a->GetNumColumns();
  y2 = b->GetNumColumns();

  if (y1 != y2) {
    cerr << "Tables non-equivalent" << endl;
    cerr << "Comparing tables " <<  a->GetName() << " has column length " << y1 << endl;
    cerr << "Comparing tables " <<  b->GetName() << " has column length " << y2 << endl;
    return -2;
  }

  a1 = a->GetColumnNames();
  b1 = b->GetColumnNames();

  if (CompareStringArrays(a1, b1)) {
    cerr << "Tables non-equivalent" << endl;
    cerr << "Column names are not equivalent." << endl;
    return -3;
  }
  if (a1) delete a1; a1 = NULL;
  if (b1) delete b1; b1 = NULL;


  for (i = 0; i < x1; i++) {
    a1 = a->GetRow(i);
    b1 = b->GetRow(i);
    if (CompareStringArrays(a1, b1)) {
     cerr << "Tables non-equivalent" << endl;
     cerr << "Mismatch detected in row " << i << endl;
     for (j=0; j < (int)a1->Length(); j++) {
       cerr << "Column [" << j << "] "<< (*a1)[j].Text() << (*b1)[j].Text() << endl;
     }
     return (-4 - i);
    }
    if (a1) delete a1; a1 = NULL;
    if (b1) delete b1; b1 = NULL;
  }

  for (i = 0; i < y1; i++) {
    a1 = a->GetColumn(i);
    b1 = b->GetColumn(i);
    if (CompareStringArrays(a1, b1)) {
     cerr << "Tables non-equivalent" << endl;
     cerr << "Mismatch detected in column " << i << endl;
     for (j=0; j < (int)a1->Length(); j++) {
       cerr << "Row [" << j << "] "<< (*a1)[j].Text() << (*b1)[j].Text() << endl;
     }
     return (-4 - x1 - i);
    }
    if (a1) delete a1; a1 = NULL;
    if (b1) delete b1; b1 = NULL;
  }
  return 1;
}



int CompareStringArrays(ReVarCifArray<CifString> * a, ReVarCifArray<CifString> * b) {
  if ((!a) && (!b)) return 0;
  if (!a) return -1;
  if (!b) return -2;
  int alen = a->Length();
  int blen = b->Length();
  if (alen != blen) return -3;
  for (int i = 0; i < alen; i++) {
    if (strcmp((*a)[i].Text(), (*b)[i].Text()))
      return (-4 - i);
  }

  return 0;
}
