/* Copyright (C) 2003-2008 by the 
 * Institute of Global Environment and Society (IGES)
 * See the file COPYRIGHT for more information.   
 *
 *
 * gaUtils.cc  - Some functions and structures shared by gaConnect and
 *  gaReports, for parsing the DDS. Really this should be a class, gaVars,
 *  that both gaConnect and gaReports have an instance of. 
 *
 * Last modified: $Date: 2008/07/25 20:43:25 $ 
 * Revision for this file: $Revision: 1.4 $
 * Release name: $Name: gadods-2_0 $
 * Original for this file: $Source: /homes/cvsroot/gadods/gadods/src/gaUtils.cc,v $
 */

#include "gadap.h"
#include "gadap_err.h"
#include "gaUtils.h"
#include <Structure.h>
#include <Sequence.h>
#include <Grid.h>
#include <Array.h>
#include <BaseType.h>
#include <strstream>

Sequence * findOuterSequence(DDS &dds) {
  BaseType * cur = NULL;
  DDS::Vars_iter p0 = dds.var_begin();
  while (p0 != dds.var_end()) {
    cur = *p0;
    // cout << "top level: " << cur->name() << endl;
    if (cur->type() == dods_sequence_c) {
      return dynamic_cast<Sequence *>(cur);
    }
    ++p0; // Added jhrg (I didn't see any prev code to incr the iter/Pix
  }
  return NULL;
}

Sequence * findInnerSequence(Sequence * outer) {
  BaseType * cur = NULL;
  // Pix p0 = outer->first_var();
  Constructor::Vars_iter p0 = outer->var_begin();
  while (p0 != outer->var_end()) {
    // cur = outer->var(p0);
    cur = *p0;
    // cout << "top level: " << cur->name() << endl;
    if (cur->type() == dods_sequence_c) {
      return dynamic_cast<Sequence *>(cur);
    }
    // outer->next_var(p0);
    ++p0;
  }
  return NULL;
}

/** Used by parseVars */
void parseSingleVar(vector<gadap_varinfo> &variables, 
		   string base_name, 
		   BaseType * var) {
  Array * array;
  gadap_varinfo info;
  info.name = var->name();
  info.longname = base_name + var->name();
  info.length = 1;
  info.type = GADAP_DBL_TYPE;

  // get main array out of grid
  if (var->type() == dods_grid_c) {
    Grid * grid = dynamic_cast<Grid *>(var);
    var = grid->array_var();
  }
    
  switch (var->type()) {
  case dods_array_c:
    array = dynamic_cast<Array *>(var);
    info.length = array->length();
    break;
  case dods_str_c:
  case dods_url_c:
    info.type = GADAP_STR_TYPE;
    break;
  }
  
  variables.push_back(info);
}

/** Used by parseVars */
int parseStructure(vector<gadap_varinfo> &variables, 
		   string base_name, 
		   Structure * structure) {
  BaseType *var;
  gadap_varinfo info;
  base_name = base_name + structure->name() + ".";
  // Pix p = structure->first_var();
  Constructor::Vars_iter p = structure->var_begin();
    int numVars = 0;
    while (p != structure->var_end()) {
    var = *p;      

    if (var->type() == dods_structure_c) {
      numVars += parseStructure(variables, base_name, 
				dynamic_cast<Structure *>(var));
    } else if (var->type() == dods_sequence_c) {
      // skip
    } else {
      parseSingleVar(variables, base_name, var);
      numVars++;
    }
    //structure->next_var(p);
    ++p;
  }
  return numVars;
}


/** Used by parseVars */
int parseSequence(vector<gadap_varinfo> &variables, 
		  string base_name, 
		  Sequence * sequence) {
  BaseType *var;
  base_name = base_name + sequence->name() + ".";
  // Pix p = sequence->first_var();
  Constructor::Vars_iter p = sequence->var_begin();
  int numVars = 0;
  while (p != sequence->var_end()) {
    var = *p;      
    if (var->type() == dods_structure_c) {
      numVars += parseStructure(variables, base_name, 
				dynamic_cast<Structure *>(var));
    } else if (var->type() == dods_sequence_c) {
      // do nothing
    } else {
      parseSingleVar(variables, base_name, var);
      numVars++;
    }
    // sequence->next_var(p);
    ++p;
  }
  return numVars;
}


/** Extracts the column names of a two-level sequence into a list of
 *    name pairs (short name first, long name second).  Variables from
 *    the outer level come first; variables from the inner level come
 *    second.  The number of outer-level variables is returned in
 *    numIVars.  Used by both gaConnect and gaReports.
 */
void parseVars(vector<gadap_varinfo> &variables, DDS &dds, int &numIVars) {

  Sequence * outer = findOuterSequence(dds);
  if (outer) {
    numIVars = parseSequence(variables, "", outer);
    Sequence * inner = findInnerSequence(outer);
    if (inner) {
      parseSequence(variables, outer->name() + ".", inner);
    }
  }

}


string &removeQuotes(string &input) {
  if (input[0] == '"') {
    input.erase(0, 1);
  }
  if (input[input.length() - 1] == '"') {
    input.erase(input.length() - 1);
  }
  return input;
}
