/* Copyright (C) 2003-2008 by the 
 * Institute of Global Environment and Society (IGES)
 * See the file COPYRIGHT for more information.   
 *
 *
 * gadap.h : GrADS Client Interface for accessing OPeNDAP in-situ data. 
 *
 * Original Author: Joe Wielgosz 
 *   with modifications by James Gallagher, Arlindo daSilva, and Jennifer Adams
 *
 * Maintained by Jennifer Adams <jma@cola.iges.org>
 *
 */ 

#ifndef _gadap_h_
#define _gadap_h_

/* Error codes */
#include "gadap_err.h"
#include "gadap_types.h"

#if defined(__cplusplus)
extern "C" {
#endif


/*****************************************************************
 * Naming conventions:
 *
 * All defined types and macros are in all upper-case, and begin with 
 * "GADAP_". All functions are in all lower-case and begin with "gadap_". 
 * Many functions begin with "gadap_x_" where x is an abbreviation 
 * for the type of structure the function acts on. A handle or pointer
 * to that structure will generally be the first argument of such a function.
 *
 * For instance, 
 *   int gadap_d_numvars(GADAP_DATASET d_handle)
 * is a function that acts on a dataset ("d") whereas 
 *   int gadap_r_numvars(GADAP_RPTCOL r_handle)
 * acts on a report collection ("r").
 *
 * Indices: 
 *
 * All indices are zero-based.
 *
 * Memory management: 
 *
 * Only memory allocated directly by the user (i.e. with a call to
 * malloc) should be freed directly by the user. All memory allocated
 * by the library will be freed when the various gadap_x_free
 * functions are called.
 *  
 *
 * Error handling:
 *
 * Functions with return type GADAP_STATUS: 
 * Success is indicated by returning GADAP_SUCCESS (zero). 
 * An error is indicated by a negative return value. A complete list of
 * these values is in "gadap_err.h".
 *
 * Functions with return type int: 
 * An error is indicated by a negative return value. A complete list of
 * these values is in "gadap_err.h".
 *
 * Functions with pointer return type: 
 * An error will be indicated by a NULL return value. No specific error 
 * information is available for these functions.
 *
 * Functions with return type void:
 * These functions should not need error-checking. 
 */


/*****************************************************************
 * Opening and closing datasets 
 */

/* Opens dataset using the URL given. The handle to the opened dataset
 * is placed in the handle argument. If the open attempt fails, 
 * the handle will be set to a negative (invalid) value. */
GADAP_STATUS 
gadap_open(const char *url, GADAP_DATASET *d_handle);

/* Returns the number of open datasets */
int 
gadap_numopen();

/* Returns a handle for the nth open dataset */
GADAP_STATUS 
gadap_handle(GADAP_DATASET *d_handle, int d_index);

/* Closes the specified dataset, releasing all resources.
 * If the free_rptcols argument is non-zero, all existing report collections 
 * associated with this dataset will be freed. */
void 
gadap_close(GADAP_DATASET d_handle, int free_rptcols);


/*****************************************************************
 * Identifying variables 
 */

/* Returns the index of the variable with the specified name, 
 * in the specified dataset. Returns a negative error code if the 
 * variable is not present. */
int 
gadap_d_varindex(GADAP_DATASET d_handle, const char *varname);

/* Returns the name of the nth variable in the specified dataset. */
const char *
gadap_d_varname(GADAP_DATASET d_handle, int var_index);


/* Returns the data type of the nth variable in the specified dataset - 
 * text, or numeric (see enum GADAP_VAR_TYPE) */
GADAP_VAR_TYPE
gadap_d_vartype(GADAP_DATASET d_handle, int var_index);

/* Returns the array size of the nth variable in the specified
 *  dataset. Non-array variables are equivalent to arrays of length
 *  1. */
int
gadap_d_varlen(GADAP_DATASET d_handle, int var_index);

/* Returns the total number of variables in the specified dataset. */
int 
gadap_d_numvars(GADAP_DATASET d_handle);

/* Returns the total number of level-independent variables in the specified 
 * dataset. Level-independent variables come first in the variable list.
 * Thus, variables with indexes 0 through (numlivars - 1) are 
 * level-independent, while those with indexes >= numlivars have multiple
 * vertical levels. */
int 
gadap_d_numlivars(GADAP_DATASET d_handle);


/*****************************************************************
 * Obtaining metadata 
 */

/* Returns the short name of the specified dataset */
const char *
gadap_d_name(GADAP_DATASET d_handle);

/* Returns the full name of the specified dataset */
const char *
gadap_d_fullname(GADAP_DATASET d_handle);

/* Returns the URL used to open the specified dataset */
const char *
gadap_d_url(GADAP_DATASET d_handle);

/* Returns the number of metadata attributes associated with the 
 * specified dataset */
int 
gadap_d_numattrs(GADAP_DATASET d_handle, int var_index);

/* Returns the name of the nth attribute of the specified dataset */
const char *
gadap_d_attrname(GADAP_DATASET d_handle, int var_index, int attr_index);

/* Returns the index of the attribute with the specified name in the
   specified dataset. Returns a negative error code if the attribute is
   not present. */
int 
gadap_d_attrindex(GADAP_DATASET d_handle, int var_index, const char *attrname);

/* Returns the value of the nth attribute of the specified dataset,
 * as a string. */
const char *
gadap_d_attrstr(GADAP_DATASET d_handle, int var_index, int attr_index);

/* Places the numeric value of the nth attribute of the specified
 * dataset in the value argument. If the attribute cannnot be converted
 * to a numerical representation, value is not set, and an error is 
 * indicated in the return value */
GADAP_STATUS
gadap_d_attrdbl(GADAP_DATASET d_handle, int var_index, int attr_index, 
		 double *value);


/*****************************************************************
 * Metadata convenience functions
 */

/* Returns the title of the specified dataset (the global attribute 
 * "title")
 */
const char *
gadap_d_title(GADAP_DATASET d_handle); 

/* Places the missing data value for the nth variable of the specified dataset 
 * in the value argument (the attribute with name "missing_value" or else "_FillValue"). 
 * If the variable specified has no fill value, value is not set, and 
 * an error is indicated in the return value */
GADAP_STATUS
gadap_d_fill(GADAP_DATASET d_handle, int var_index, double *value); 

/* Returns the long name for the nth variable of the specified dataset
 * (the attribute with name "long_name").
 */
const char *
gadap_d_longname(GADAP_DATASET d_handle, int var_index); 

/*****************************************************************
 * Sending a query 
 */

/* Allocates memory for a station data query, and also allocates the query's 
 * varflags array with the correct number of elements for the specified 
 * dataset. All float and int values are initialized to zero, and strings to 
 * NULL. 
 */
GADAP_STN_QUERY *
gadap_sq_new(GADAP_DATASET d_handle);

/* Populates the constraint and url fields of the query structure with the
 * based on the current query settings. This can be used to print or examine
 * the request URL before the request is actually sent.
 */
const char *
gadap_sq_url(GADAP_STN_QUERY *query);

/* Makes the specified query on the specified dataset. If successful, a 
 * handle to the resulting report collection is placed in the r_handle 
 * argument. The report collection makes its own copy of the query structure; 
 * the caller is responsible for disposing of the query 
 * passed in once it has been used, by calling gadap_sq_free(). */
GADAP_STATUS
gadap_sq_send(GADAP_STN_QUERY *query,
	       GADAP_RPTCOL *r_handle);

/* Frees memory for a station data query, including the varflag array. 
 * The caller is responsible for freeing memory used by the query's string 
 * fields (mintime, maxtime, stid, and extra) if they have been allocated. */
void
gadap_sq_free(GADAP_STN_QUERY *query);


/*****************************************************************
 * Managing report collections 
 */

/* Puts in the d_handle argument a handle to the dataset associated with the  
 * specified report collection (if the associated dataset is still open).*/
GADAP_STATUS
gadap_r_dataset(GADAP_RPTCOL r_handle, GADAP_DATASET *d_handle);

/* Returns the URL that was used to generate this report.
 */
const char *
gadap_r_url(GADAP_RPTCOL r_handle);

/* Returns the query that was used to generate this report.
 * The caller should NOT free the memory for this query.
 */
GADAP_STN_QUERY *
gadap_r_query(GADAP_RPTCOL r_handle);

/* Returns the total number of variables in the specified report collection */
int 
gadap_r_numvars(GADAP_RPTCOL r_handle);

/* Returns the total number of level-independent variables in the specified 
 * report collection. Level-independent variables come first in the variable
 * list. Thus, variables with indexes 0 through (numlivars - 1) are 
 * level-independent, while those with indexes >= numlivars have multiple
 * vertical levels. */
int 
gadap_r_numlivars(GADAP_RPTCOL r_handle);

/* Returns the name of the nth variable in the specified report collection  */
const char *
gadap_r_varname(GADAP_RPTCOL r_handle, int var_index);

/* Returns the index of the variable with the specified name, 
 * in the specified dataset. Returns a negative error code if the 
 * variable is not present. */
int
gadap_r_varindex(GADAP_RPTCOL r_handle, const char *varname);

/* Returns the total number of reports in the specified report collection */
int 
gadap_r_numrpts(GADAP_RPTCOL r_handle);

/* Returns the total number of vertical levels in the specified report of the 
 * specified report collection */
int 
gadap_r_numlev(GADAP_RPTCOL r_handle, int rpt_index);

/* Frees all resources used by the specified report collection.  */
void
gadap_r_free(GADAP_RPTCOL r_handle);


/*****************************************************************
 * Retrieving data from report collections 
 */

/* Returns the value of the nth variable of the specified report
 * collection, at the specified level of the specified report, in
 * double-precision floating point form. If the variable is
 * level-independent, the value of lev_index is ignored. The
 * array_index specifies which element to retrieve if the variable is
 * an array, otherwise it is ignored. If the variable is a string
 * variable, value is not set, and an error code is returned.
 */
GADAP_STATUS
gadap_r_valdbl(GADAP_RPTCOL r_handle, 
		int rpt_index, int lev_index, int var_index, int array_index,
		double * value);

/* Returns the value of the nth variable of the specified report
 * collection, at the specified level of the specified report, in
 * string form. If the variable is level-independent, the value of
 * lev_index is ignored. The array_index specifies which element to
 * retrieve if the variable is an array, otherwise it is ignored. If
 * the variable is not a string variable, a null pointer is
 * returned. */
const char *
gadap_r_valstr(GADAP_RPTCOL r_handle, 
		int rpt_index, int lev_index, int var_index, int array_index);


#if defined(__cplusplus)
}
#endif

#endif /* _gadap_h_ */


