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

#define MxStrLen   30

char _sybaseVarType[][MxStrLen] = 
  {"int",  "float",  "varchar",  "varchar",  "varchar",  "varchar", "datetime", 
     "text"};


char _matrixField[][MxStrLen] = {
  "m11","m12","m13","m21","m22","m23",
  "m31","m32","m33", "v1","v2","v3"};


//extern "C" {
// int strcasecmp (const char *s1, const char *s2);
// int strncasecmp (const char *s1, const char *s2, size_t n);
// int symlink(const char *s1, const char *s2);
//}




#define FALSE 0
#define TRUE  1

int main() {
  char *diags=NULL;
  CifFileObj * fobjR = NULL;
  int i;
  CifString question;
  question.Copy("?");

  fobjR = new CifFileObj("./test/SCHEMA.odb", WRITE_MODE, 80, "?", 0);

  fobjR->Read("./test/ndb_tokens.cif",diags);
  if (diags) {
    cout << " Diagnostics [" << strlen(diags) << "] " << diags << endl;
    delete diags;
  }

  fobjR->Read("./test/ndb_cif.cif",diags);
  if (diags) {
     cout << " Diagnostics [" << strlen(diags) << "] " << diags << endl;
     delete diags;
  }

  fobjR->Read("./test/ndb_schema.cif",diags);
  if (diags) {
     cout << " Diagnostics [" << strlen(diags) << "] " << diags << endl;
     delete diags;
  }
  fobjR->CloseFile();
  delete fobjR;

  fobjR = new CifFileObj("./test/SCHEMA.odb", READ_MODE, 80, "?", 0);
//    fobjR->Write("SCHEMA.cif");
  ISTable *schema = fobjR->GetTablePtr("NDB_SCHEMA","ndb_table_field");

  ISTable *scinfo  = fobjR->GetTablePtr("NDB_SCHEMA","ndb_schema_info");
  ISTable *scfinfo = fobjR->GetTablePtr("NDB_SCHEMA","ndb_schema_info_field");


  ISTable *tokens = fobjR->GetTablePtr("NDB_TOKENS","ndb_field");
  ISTable *tinfo  = fobjR->GetTablePtr("NDB_TOKENS","ndb_token");
  ISTable *jinfo  = fobjR->GetTablePtr("NDB_TOKENS","jrnl_token");
  ISTable *jtokens = fobjR->GetTablePtr("NDB_TOKENS","jrnl_field");
  ISTable *cifkw  = fobjR->GetTablePtr("NDB_CIF","ndb_cif_keyword");



  ReVarCifArray<CifString> *c0 = NULL;
  c0 = new  ReVarCifArray<CifString>;
  ReVarPCifArray<int> *i0 = NULL;
  i0 = new  ReVarPCifArray<int>;

  int errCode;
  CifString itemName;
  int iType=0, iWidth, iPrec, irow, iMatrix=0, iContNo=0, ifNumb, iq=0;
  CifString csType, csWidth, csPrec, dType;
  CifString colName;
  ReVarPCifArray<int> * ir = NULL;
  ReVarCifArray<CifString> *row = NULL;

  ReVarCifArray<CifString> *tNames = schema->GetColumn(0);
  ReVarCifArray<CifString> *fNames = schema->GetColumn(1);
  ReVarCifArray<CifString> *fNumbs = schema->GetColumn(2);

  ReVarCifArray<CifString> *scol3  = schema->GetColumn(3);
  ReVarCifArray<CifString> *scol4  = schema->GetColumn(4);
  ReVarCifArray<CifString> *scol5  = schema->GetColumn(5);
  //  ReVarCifArray<CifString> *scol6  = schema->GetColumn(6);
  ReVarCifArray<CifString> *scol7  = schema->GetColumn(7);
  ReVarCifArray<CifString> *scol8  = schema->GetColumn(8);
  ReVarCifArray<CifString> *scol9  = schema->GetColumn(9);
  ReVarCifArray<CifString> *scol10 = schema->GetColumn(10);

  ReVarCifArray<CifString> *scfic0 = scfinfo->GetColumn(0); //table
  ReVarCifArray<CifString> *scfic1 = scfinfo->GetColumn(1); //attribute
  ReVarCifArray<CifString> *scfic2 = scfinfo->GetColumn(2); //data type code
  ReVarCifArray<CifString> *scfic3 = scfinfo->GetColumn(3); // length
  ReVarCifArray<CifString> *scfic4 = scfinfo->GetColumn(4); // null flag
  ReVarCifArray<CifString> *scfic5 = scfinfo->GetColumn(5); // index 
  ReVarCifArray<CifString> *scfic6 = scfinfo->GetColumn(6); // www select
  ReVarCifArray<CifString> *scfic7 = scfinfo->GetColumn(7); // www report
  ReVarCifArray<CifString> *scfic8 = scfinfo->GetColumn(8); // description
  ReVarCifArray<CifString> *scfic9 = scfinfo->GetColumn(9); // example


  ReVarCifArray<CifString> *scic0 = scinfo->GetColumn(0); // table
  ReVarCifArray<CifString> *scic1 = scinfo->GetColumn(1); // table type
  ReVarCifArray<CifString> *scic2 = scinfo->GetColumn(2); // www select
  ReVarCifArray<CifString> *scic3 = scinfo->GetColumn(3); // www report
  ReVarCifArray<CifString> *scic4 = scinfo->GetColumn(4); // group_name
  ReVarCifArray<CifString> *scic5 = scinfo->GetColumn(5); // description 

  //
  // Table of attribute definitions ...
  //

  CifFileObj *fobjW = new CifFileObj("./test/NEWSCHEMA.odb", WRITE_MODE, 131, "?", 0);

  ISTable *t1  = new ISTable("rcsb_attribute_def");
  t1->AddColumn("table_name",     TRUE);
  t1->AddColumn("attribute_name", TRUE);
  t1->AddColumn("data_type",      TRUE);
  t1->AddColumn("index_flag",     TRUE);
  t1->AddColumn("null_flag",      TRUE);

  t1->AddColumn("width",          TRUE);
  t1->AddColumn("precision",      TRUE);


  
  ISTable *t2  = new ISTable("rcsb_attribute_description");
  t2->AddColumn("table_name",     TRUE);
  t2->AddColumn("attribute_name", TRUE);
  t2->AddColumn("description",    TRUE);
  t2->AddColumn("example",        TRUE);


  ISTable *t3  = new ISTable("rcsb_attribute_view");
  t3->AddColumn("table_name",     TRUE);
  t3->AddColumn("attribute_name", TRUE);
  t3->AddColumn("format_type",    TRUE); // 
  t3->AddColumn("www_select",     TRUE);
  t3->AddColumn("www_report",     TRUE);


  ISTable *t4  = new ISTable("rcsb_attribute_map");
  t4->AddColumn("target_table_name",      TRUE);
  t4->AddColumn("target_attribute_name",  TRUE);
  t4->AddColumn("source_item_name",       TRUE);
  t4->AddColumn("condition_id",           TRUE);
  t4->AddColumn("function_id",            TRUE);

  ISTable *t7  = new ISTable("rcsb_map_condition");
  t7->AddColumn("condition_id",    TRUE);
  t7->AddColumn("attribute_name",  TRUE);
  t7->AddColumn("attribute_value", TRUE);


  int it=1, ic=0;
  CifString cnd, categoryName, qName, qValue;
  qValue.Clear(); qValue.Copy("datablockid()");
  for (i=0; i < (int) tNames->Length(); i++) {
    cout << "Table =  " <<(*tNames)[i].Text() << " " 
	 << "Token =  " <<(*fNames)[i].Text() << " " 
	 << "Field =  " <<(*fNumbs)[i].Text() << " " 
	 << endl;
    if ((i>0) &&  strcmp((*tNames)[i].Text(),(*tNames)[i-1].Text())) iq = 0;

    if ((i>0) &&  strcmp((*tNames)[i].Text(),(*tNames)[i-1].Text())) {
      it++;
      ic =0;
    }
    ic++;
    //
    //  Get infomation about current Token...
    //
    if ( !strcasecmp((*scol5)[i].Text(),"none") ) {
      ir = tinfo->SearchColumn((*fNames)[i], 0 ,errCode);
      if (ir && ir->Length()) {
	row = tinfo->GetRow((*ir)[0]);
	if (row) {
	  iMatrix = atoi((*row)[4].Text());
	  iContNo = atoi((*row)[3].Text());
	  delete (row);
	}
	delete (ir);
      }
    } else {
      ir = jinfo->SearchColumn((*scol5)[i], 0 ,errCode);
      if (ir && ir->Length()) {
	row = jinfo->GetRow((*ir)[0]);
	if (row) {
	  iMatrix = atoi((*row)[4].Text());
	  iContNo = atoi((*row)[3].Text());
	  delete (row);
	}
	delete (ir);
      }

    }
    
    //
    // build the CIF item name for this attribute ... 
    //
    itemName.Clear();
    categoryName.Clear();
    ifNumb = atoi((*fNumbs)[i].Text());
    if ( !strcasecmp((*scol5)[i].Text(),"none") ) {
      c0->Clear(); c0->Add((*fNames)[i]); c0->Add((*fNumbs)[i]);
      i0->Clear(); i0->Add(2);            i0->Add(4);
    } else {
      c0->Clear(); c0->Add((*fNames)[i]); c0->Add((*fNumbs)[i]); c0->Add((*scol5)[i]);
      i0->Clear(); i0->Add(2);            i0->Add(4);            i0->Add(3);
    }
    ir = cifkw->Search(*c0, *i0,errCode);
    if (ir && ir->Length()) {
      row = cifkw->GetRow((*ir)[0]);
      if (row) {

	itemName.Copy("_");
	categoryName.Copy((*row)[0]);
	itemName += (*row)[0].Text();
	itemName += ".";
	itemName += (*row)[1].Text();
	cout << "Item Name " << itemName.Text() << endl;
	delete (row);
      }
      delete (ir);
    }

    //
    //  Get name, type, length  and precision, etc for this attribute ...
    //
    colName.Clear();
    csType.Clear();
    csWidth.Clear(); 
    csPrec.Clear(); 
    if ( !strcasecmp((*scol5)[i].Text(),"none") ) {
      ir = tokens->SearchColumn((*fNames)[i], 0 ,errCode);
      if (ir && ir->Length()) {
	irow = atoi((*fNumbs)[i].Text());
	if (irow  >= 1) {
	  row = tokens->GetRow((*ir)[irow-1]);
	  if (row) {
	    if (iMatrix && ifNumb >=2 && ifNumb <= 13 && iq <= 11) {

	      //      colName.Copy(_matrixField[ifNumb-2]);
	      //	      if (iq > 11) iq = 0;
	      colName.Copy(_matrixField[iq]); 
	      iq++; 
	    } else {
	      colName.Copy((*row)[1].Text());
	      if (ifNumb == 1) colName += "_Y_N";
	    }
	    iType  = atoi((*row)[2].Text());
	    csType.Copy((*row)[2].Text());
	    iWidth = atoi((*row)[3].Text());
	    csWidth.Copy((*row)[3].Text());
	    iPrec  = atoi((*row)[4].Text());
	    csPrec.Copy((*row)[4].Text());
	    cout << " Column Name " << colName.Text() 
		 << " Type " << iType << " Width " << iWidth 
		 << " Precision " << iPrec
		 << endl;
	    delete (row);
	  }
	}
	delete (ir);
      }
    } else {
      ir = jtokens->SearchColumn((*scol5)[i], 0 ,errCode);
      if (ir && ir->Length()) {
	irow = atoi((*fNumbs)[i].Text());
	if (irow  >= 1) {
	  row = jtokens->GetRow((*ir)[irow-1]);
	  if (row) {
	    colName.Clear(); colName.Copy((*row)[1].Text());
	    iType  = atoi((*row)[2].Text());
	    csType.Clear(); csType.Copy((*row)[2].Text());
	    iWidth = atoi((*row)[3].Text());
	    csWidth.Clear(); csWidth.Copy((*row)[3].Text());
	    iPrec  = atoi((*row)[4].Text());
	    csPrec.Clear(); csPrec.Copy((*row)[4].Text());
	    cout << " Column Name " << colName.Text() 
		 << " Type " << iType << " Width " << iWidth 
		 << " Precision " << iPrec
		 << endl;
	    delete (row);
	}
	}
	delete (ir);
      }


    }
    //
    // Build new tables here ...
    // 
    t1->AddRow();
    t1->AddElementToRow((*tNames)[i],i);    
    t1->AddElementToRow(colName,i);    
    
    dType.Clear();
    switch (iType) {
    case 1:  
      dType.Copy("int");
      break;
    case 2:
      dType.Copy("float");
      break;
    case 3:
    case 4:
    case 5:
    case 6:
      dType.Copy("char");
      break;
    case 7:
      dType.Copy("datetime");
      break;
    case 8:
      dType.Copy("text");
      break;
    default:
      dType.Copy("unknown");
      break;
    }
    t1->AddElementToRow(dType,i);    //type

    t1->AddElementToRow((*scol4)[i],i);    //index
    t1->AddElementToRow((*scol3)[i],i);    //null

    if (ifNumb == iContNo) csWidth.Copy("255");
    t1->AddElementToRow(csWidth,i);    
    t1->AddElementToRow(csPrec,i);    

    t2->AddRow();
    t2->AddElementToRow((*tNames)[i],i);    
    t2->AddElementToRow(colName,i);    
    t2->AddElementToRow((*scol9)[i],i);    //description
    t2->AddElementToRow((*scol10)[i],i);   // example 

    t3->AddRow();
    t3->AddElementToRow((*tNames)[i],i);    
    t3->AddElementToRow(colName,i);    
    t3->AddElementToRow(csType,i);    
    t3->AddElementToRow((*scol7)[i],i);    // www select
    t3->AddElementToRow((*scol8)[i],i);    // www report

    t4->AddRow();
    t4->AddElementToRow((*tNames)[i],i);    
    t4->AddElementToRow(colName,i);    
    t4->AddElementToRow(itemName,i);    
    cnd.Clear();
    if (itemName.Length()){
      //cnd.Copy("T"); cnd+= it; cnd+="C"; cnd+=ic;
       cnd.Copy("C1");
    } 
    t4->AddElementToRow(cnd,i);    
    t4->AddElementToRow(question,i);    

#
    
  }

  t7->AddRow();
  cnd.Copy("C1");
  t7->AddElementToRow(cnd,0);    
  qName.Clear();
  qName.Copy("entry_id");
  t7->AddElementToRow(qName,0);    
  t7->AddElementToRow(qValue,0);    
    


  for (i=0; i < (int) scfic0->Length(); i++) {
    irow = t1->GetNumRows();
    //
    // Build new tables here ...
    // 
    t1->AddRow();
    t1->AddElementToRow((*scfic0)[i],irow);    
    t1->AddElementToRow((*scfic1)[i],irow);    
    
    dType.Clear();
    iType = atoi((*scfic2)[i].Text());
    switch (iType) {
    case 1:  
      dType.Copy("int");
      break;
    case 2:
      dType.Copy("double");
      break;
    case 3:

    case 4:
    case 5:
    case 6:
      dType.Copy("char");
      break;
    case 7:
      dType.Copy("datetime");
      break;
    case 8:
      dType.Copy("text");
      break;
    default:
      dType.Copy("unknown");
      break;
    }
    t1->AddElementToRow(dType,irow);           //type

    t1->AddElementToRow((*scfic5)[i],irow);    //index
    t1->AddElementToRow((*scfic4)[i],irow);    //null
    //    t1->AddElementToRow((*scfic2)[i],irow);    //type
    t1->AddElementToRow((*scfic3)[i],irow);    //width
    csPrec.Clear(); csPrec.Copy("0");
    t1->AddElementToRow(csPrec,irow);    

    irow = t2->GetNumRows();

    t2->AddRow();
    t2->AddElementToRow((*scfic0)[i],irow);    
    t2->AddElementToRow((*scfic1)[i],irow);    
    t2->AddElementToRow((*scfic8)[i],irow);    //description
    t2->AddElementToRow((*scfic9)[i],irow);   // example 

    irow = t3->GetNumRows();
    t3->AddRow();
    t3->AddElementToRow((*scfic0)[i],irow);    
    t3->AddElementToRow((*scfic1)[i],irow);    
    t3->AddElementToRow((*scfic2)[i],irow);    // type code
    t3->AddElementToRow((*scfic6)[i],irow);    // www select
    t3->AddElementToRow((*scfic7)[i],irow);    // www report

    irow = t4->GetNumRows();
    t4->AddRow();
    t4->AddElementToRow((*scfic0)[i],irow);    
    t4->AddElementToRow((*scfic1)[i],irow);
    itemName.Clear();    
    t4->AddElementToRow(itemName,irow);    
  }

  // 
  // Create table RCSB_TABLE
  //

  int ind0, ind1, ind2, ind3, ind4, ind5;
  ISTable *table  = fobjR->GetTablePtr("NDB_SCHEMA","ndb_table");

  ind0=table->GetColumnIndex("table_name");
  ind1=table->GetColumnIndex("description");
  ind2=table->GetColumnIndex("table_type");
  ind3=table->GetColumnIndex("www_selection");
  ind4=table->GetColumnIndex("www_report");
  ind5=table->GetColumnIndex("group_name");

  ISTable *t5  = new ISTable("rcsb_table_description");
  t5->AddColumn("table_name",      TRUE);
  t5->AddColumn("description",     TRUE);
  
  if (ind0 >= 0 && ind1 >= 0) {
    ReVarCifArray<CifString> *c0 = table->GetColumn(ind0);
    ReVarCifArray<CifString> *c1 = table->GetColumn(ind1);
    t5->FillColumn(*c0,0);
    t5->FillColumn(*c1,1);
    delete c0;
    delete c1;
  }

  for (i=0; i < (int) scic0->Length(); i++) {
    irow = t5->GetNumRows();
    t5->AddRow();
    t5->AddElementToRow((*scic0)[i],irow);    
    t5->AddElementToRow((*scic5)[i],irow);    
  }


  ISTable *t6  = new ISTable("rcsb_table");
  t6->AddColumn("table_name",     TRUE);
  t6->AddColumn("table_type",     TRUE);
  t6->AddColumn("group_name",     TRUE);
  t6->AddColumn("www_select",     TRUE);
  t6->AddColumn("www_report",     TRUE);
  
  if (ind0 >= 0 && ind2 >= 0 && ind3 >= 0 && ind4 >= 0 && ind5 >= 0 ) {
    ReVarCifArray<CifString> *c0 = table->GetColumn(ind0);
    ReVarCifArray<CifString> *c2 = table->GetColumn(ind2);
    ReVarCifArray<CifString> *c3 = table->GetColumn(ind3);
    ReVarCifArray<CifString> *c4 = table->GetColumn(ind4);
    ReVarCifArray<CifString> *c5 = table->GetColumn(ind5);
    t6->FillColumn(*c0,0);
    t6->FillColumn(*c2,1);
    t6->FillColumn(*c5,2);
    t6->FillColumn(*c3,3);
    t6->FillColumn(*c4,4);

    delete c0;
    delete c2;
    delete c3;
    delete c4;
    delete c5;
  }

  for (i=0; i < (int) scic0->Length(); i++) {
    irow = t6->GetNumRows();
    t6->AddRow();
    t6->AddElementToRow((*scic0)[i],irow);    
    t6->AddElementToRow((*scic1)[i],irow);    
    t6->AddElementToRow((*scic4)[i],irow);    
    t6->AddElementToRow((*scic2)[i],irow);    
    t6->AddElementToRow((*scic3)[i],irow);    
  }


  fobjW->WriteTable(t6,"rcsb_schema",t6->GetName());
  fobjW->WriteTable(t1,"rcsb_schema",t1->GetName());

  fobjW->WriteTable(t5,"rcsb_schema",t5->GetName());
  fobjW->WriteTable(t2,"rcsb_schema",t2->GetName());
  fobjW->WriteTable(t3,"rcsb_schema",t3->GetName());

  fobjW->Write("./test/new_rcsb_schema.cif");

  fobjW->CloseFile();

  CifFileObj *fobjM = new CifFileObj("./test/SCHEMAMAP.odb", WRITE_MODE, 131, "?", 0);
  fobjM->WriteTable(t4,"rcsb_schema_map",t4->GetName());
  fobjM->WriteTable(t7,"rcsb_schema_map",t7->GetName());
  fobjM->Write("./test/new_rcsb_schema_map.cif");

  fobjM->CloseFile();


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

  exit(0);
}
