/* Copyright (C) 2003-2008 by the 
 * Institute of Global Environment and Society (IGES)
 * See the file COPYRIGHT for more information.   
 *
 * test.cc - test program for gadap library. 
 *
 */

#include "gadap.h"
#include <iostream>
#include <string>

using namespace std;

bool test_openclose(const char *url);

int main(int argc, char *argv[]) {

  double attrValue;

  if (argc <= 1) {
    cout << "need URL\n";
    return 0;
  } 

  //  cout << "press a key to load metadata..." << endl;
  //  cin.get();

  cout << endl << "Connecting to URL " << argv[1] << " ... " << endl;
   
  //  test_openclose(argv[1]);
  
  GADAP_DATASET handle;
  int success = gadap_open(argv[1], &handle);
  if (success == GADAP_SUCCESS) {
    cout << "ok!" << endl;
  } else {
    cout << "failed!" << endl;
    exit(1);
  }

  //  cout << "# DATASETS OPEN: " << gadap_numopen() << endl <<endl;
  cout << endl<<"    URL: " << gadap_d_url(handle) << endl;
  cout << "DATASET: " << gadap_d_name(handle) << endl;

  if (gadap_d_title(handle)) {
    cout << "  TITLE: " << gadap_d_title(handle)  << endl;
  }

  cout << endl<<"GLOBAL ATTRIBUTES: " << endl;
  for (int i = 0; i < gadap_d_numattrs(handle, -1); i++) {
    cout << "  " << gadap_d_attrname(handle, -1, i) << " (" 
	 << gadap_d_attrindex(handle, -1, gadap_d_attrname(handle, -1, i));
    cout << "): " << gadap_d_attrstr(handle, -1, i) << " (numeric: ";
    if (gadap_d_attrdbl(handle, -1, i, &attrValue) == GADAP_SUCCESS) {
      cout << attrValue; 
    } else {
      cout << "none";
    }
    cout << ")\n";
  }

  cout << endl<<"VARIABLES: " << gadap_d_numvars(handle) << " (" 
       << gadap_d_numlivars(handle) << " surface)" << endl;
  for (int i = 0; i < gadap_d_numvars(handle); i++) {
    string varname(gadap_d_varname(handle, i));
    const char * units = gadap_d_attrstr(handle, i, gadap_d_attrindex(handle, i, "units"));
    const char * longname;
    double fill;
    cout << "  " << gadap_d_varindex(handle, varname.c_str()) 
	   << "  " << varname << "[" << gadap_d_varlen(handle, i) << "] (";

      if (units) { 
	cout << "units:" << units;
      } else {
	cout << "no units";
      }
      if (gadap_d_fill(handle, i, &fill) == GADAP_SUCCESS) {
	cout << ", fill: " << fill;
      }

      longname = gadap_d_longname(handle, i);
      cout << ") --- ";
      if (longname) {
	cout << longname << endl; 
      } else {
	cout << "no longname" << endl;
      }

      /*
      cout << "  attrs for " << varname << ":" << endl;
      for (int j = 0; j < gadap_d_numattrs(handle, i); j++) {
	cout << "    " << gadap_d_attrname(handle, i, j) << " (" 
	     << gadap_d_attrindex(handle, i, gadap_d_attrname(handle, i, j));
	cout << "): " << gadap_d_attr(handle, i, j) << " (numeric: ";
	if (gadap_d_attrdbl(handle, i, j, &attrValue) == GADAP_SUCCESS) {
	  cout << attrValue; 
	} else {
	  cout << "none";
	}
	cout << ")" << endl;
      }
      cout << endl;
      */

  }


  if (argc <= 3) {
    cout << endl << "no data requested" << endl;
      exit(0);
  }

  cout << endl<<"DATA FOR VARIABLES: " << argv[2] << " to " 
       << argv[3] << endl;

  GADAP_STN_QUERY *query = gadap_sq_new(handle);

  int varindex1 = atoi(argv[2]);
  int varindex2 = atoi(argv[3]);


  for (int i = varindex1; i <= varindex2; i++) {
    query->varflags[i] = true;
  }

  if (argc > 4) {
      if (strcmp(argv[4], "-s") == 0) {
	  if (argc > 5) {
	      query->stid = argv[5];
	  } else {
	      cout << "missing stid for -s flag" << endl;
	      exit(1);
	  }
      } else if (strcmp(argv[4], "-b") == 0) {
	  if (argc > 12) {
	      query->usebounds = 1;
	      query->minlon = atof(argv[5]);
	      query->maxlon = atof(argv[6]);
	      query->minlat = atof(argv[7]);
	      query->maxlat = atof(argv[8]);
	      query->minlev = atof(argv[9]);
	      query->maxlev = atof(argv[10]);
	      query->mintime = argv[11];
	      query->maxtime = argv[12];
	  } else {
	      cout << "missing x1, x2, y1, y2, z1, z2, t1, t2 for -b flag" 
		   << endl;
	      exit(1);
	  }
      } else if (strcmp(argv[4], "-sb") == 0) {
	  if (argc > 9) {
	      query->stid = argv[5];
	      query->usebounds = 1;
	      query->minlon = 0.0;
	      query->maxlon = 0.0;
	      query->minlat = 0.0;
	      query->maxlat = 0.0;
	      query->minlev = atof(argv[6]);
	      query->maxlev = atof(argv[7]);
	      query->mintime = argv[8];
	      query->maxtime = argv[9];
	  } else {
	      cout << "missing stid, z1, z2, t1, t2 for -sb flag" 
		   << endl;
	      exit(1);
	  }
      } else if (strcmp(argv[4], "-x") == 0) {
	query->extra = argv[5];
      }
  }

  // cout << "press a key to load reports..." << endl;
  //    cin.get();

  cout << endl << "Querying " << gadap_sq_url(query) << " ... " << endl;

  GADAP_RPTCOL r_handle;
  if (gadap_sq_send(query, &r_handle) == GADAP_SUCCESS) {
    cout << "ok!" << endl;
  } else {
    cout << "failed! " << endl;
    return 0;
  }

  cout << endl 
       << "  REPORTS: " << gadap_r_numrpts(r_handle) <<endl;
  cout << "VARIABLES: " << gadap_r_numvars(r_handle) 
       << " (" << gadap_r_numlivars(r_handle)
       << " surface)"<<endl;
  cout << "     ROWS: " << gadap_r_numrpts(r_handle) << endl;


  double data;
  double time;
  const char * sdata;

  for (int i = 0; i < gadap_r_numrpts(r_handle); i++) {
    cout << "   Row " << i 
	 << " (" << gadap_r_numlev(r_handle, i) << " levels):" ;

    for (int j = 0; j < gadap_r_numlivars(r_handle); j++) {
      cout << " ";
      int len = gadap_d_varlen(handle, 
				gadap_d_varindex(handle, 
						  gadap_r_varname(r_handle, j)));
      if (gadap_r_valdbl(r_handle, i, 0, j, 0, &data) == GADAP_SUCCESS) {
	  cout << " " << data;
      } else {
	sdata = gadap_r_valstr(r_handle, i, 0, j, 0);
	if (sdata) {
	  cout << " " << sdata;
	}
      }
      for (int k = 1; k < len; k++) {
	if (gadap_r_valdbl(r_handle, i, 0, j, k, &data) == GADAP_SUCCESS) { 
	  cout << "," << data;
	} else {
	  sdata = gadap_r_valstr(r_handle, i, 0, j, k);
	  if (sdata) {
	    cout << " " << sdata;
	  }
	}
      }
    }
    cout << endl;

    for (int j = 0; j < gadap_r_numlev(r_handle, i); j++) {
      cout << "\t[";
      for (int k = gadap_r_numlivars(r_handle); 
	   k < gadap_r_numvars(r_handle); k++) {
	if (gadap_r_valdbl(r_handle, i, j, k, 0, &data) == GADAP_SUCCESS) {
	  cout << " " << data;
	} else {
	  cout << " (nan)";
	}
      }
      cout << "]" << endl;
    }
  }

  cout << endl<< "END OF DATA" << endl;
 
  //   cout << "press a key to close..." << endl;
  //cin.get();

  cout << endl <<"Closing reports ..." ;

  gadap_r_free(r_handle);
  cout << "ok!" << endl << flush;

  cout << "Closing URL ..." ;
  gadap_close(handle, false);
  cout << "ok!" << endl << flush;

  if ( gadap_numopen() == 0 ) {
    cout << endl << "Good, we have no more datasets open - all done! "
         <<endl<<endl;
  } else {
    cout << endl << "Strange, we still have "<<gadap_numopen()
         <<" datasets open"<<endl<<endl;

    exit(1);
  }

  // cout << "press a key to quit..." << endl;
  // cin.get();

}

// ----------------------------------------------------------------------


  bool test_openclose(const char *url) {
  cout << "opening and closing:" << endl;

  cout << "opening ten datasets..." << endl;
  GADAP_DATASET handles[15];
  int retval;
  for (int i = 0; i < 10; i++) {
    retval = gadap_open(url, &handles[i]);
    if (retval < 0) {
      cout << "error opening dataset!" << endl;
      exit(1);
    }
  }
  cout << gadap_numopen() << " datasets open." << endl;
  if (gadap_numopen() != 10) {
    return false;
  }

  GADAP_DATASET current_handle;
  for (int i = 0; i < gadap_numopen(); i++) {
    if (gadap_handle(&current_handle, i) != GADAP_SUCCESS) {
      cout << i << ": no handle." << endl;
      return false;
    } 
    if (current_handle != handles[i]) {
      cout << "handle " << current_handle << " != " << handles[i] << endl;
      return false;
    }      
    string urlstring(url);
    if (urlstring != gadap_d_url(handles[i])) {
      cout << i << ": " << url << " != " << gadap_d_url(handles[i]) << endl;
      return false;
    } 
    cout << i << "(" << handles[i] << "): " << gadap_d_url(current_handle) << endl;
  }

  cout << "closing five..." << endl;
  for (int i = 0; i < 10; i += 2) {
    gadap_close(handles[i], false);
  }
  if (gadap_numopen() != 5) {
    return false;
  }

  for (int i = 1; i < 10; i += 2) {
    string urlstring(url);
    if (gadap_d_url(handles[i]) == NULL || 
	urlstring != gadap_d_url(handles[i])) {
      cout << i << ": " << url << " != " << gadap_d_url(handles[i]) << endl;
      return false;
    } 
    cout << i << "(" << handles[i] << "): " << gadap_d_url(current_handle) << endl;
  }

  for (int i = 0; i < 5; i++) {
    gadap_handle(&current_handle, i);
    if (current_handle != handles[(i*2)+1]) {
      cout << "handle " << current_handle << " != " << handles[(i*2)+1] << endl;
      return false;
    }           
    handles[i] = current_handle;
  }

  for (int i = 0; i < gadap_numopen(); i++) {
    string urlstring(url);
    if (gadap_d_url(handles[i]) == NULL || 
	urlstring != gadap_d_url(handles[i])) {
      cout << i << ": " << url << " != " << gadap_d_url(handles[i]) << endl;
      return false;
    } 
    cout << i << "(" << handles[i] << "): " << gadap_d_url(current_handle) << endl;
  }
  
  cout << "opening ten more datasets..." << endl;
  for (int i = 0; i < 10; i++) {
    gadap_open(url, &handles[i+5]);
  }

  if (gadap_numopen() != 15) {
    return false;
  }

  for (int i = 0; i < gadap_numopen(); i++) {
    string urlstring(url);
    if (urlstring != gadap_d_url(handles[i])) {
      cout << i << ": " << url << " != " << gadap_d_url(handles[i]) << endl;
      return false;
    } 
    cout << i << "(" << handles[i] << "): " << gadap_d_url(current_handle) << endl;
  }
  
  cout << "closing all of them..." << endl;
  while(gadap_numopen()) {
    gadap_handle(&current_handle, 0);
    gadap_close(current_handle, false);
  }

  cout << "test succeeded." << endl << endl;
  return true; 
}

