/*--------------------------------------------------------------------
 *	$Id: nc2xy.c,v 1.8 2006/04/18 08:48:21 pwessel Exp $
 *
 *	Copyright (c) 2006 by R. Scharroo
 *	See COPYING file for copying and redistribution conditions.
 *
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation; version 2 of the License.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	Contact info: gmt.soest.hawaii.edu
 *--------------------------------------------------------------------*/
/*
 * nc2xy.c reads a netCDF file and prints out the x,y values to
 * standard output.
 *
 * Author:	Remko Scharroo
 * Date:	28-Nov-2005
 * Version:	1
 */

#define NVAR 10
#define GMT_WITH_NO_PS
#include "gmt.h"

int main (int argc, char **argv)
{
	BOOLEAN error = FALSE, suppress = FALSE, reverse = FALSE, skip;

	int i, k, ncid, varid[NVAR], dimid = 0, ndims, n_files = 0, n_out;
	int n_total = 0, n_suppressed = 0;

	size_t len, j;

	double w, e, s, n, out[NVAR], add_offset[NVAR], scale_factor[NVAR], missing_value[NVAR];

	char varnm[NVAR][BUFSIZ];

	argc = GMT_begin (argc, argv);

	w = e = s = n = 0.0;

	for (i = 0; i < NVAR; i++) {
		varnm[i][0] = '\0';
	}

	for (i = 1; i < argc; i++) {
		if (argv[i][0] == '-') {
			switch (argv[i][1]) {
				/* Common parameters */

				case 'V':
				case '\0':
					error += GMT_parse_common_options (argv[i], &w, &e, &s, &n);
					break;

				/* Supplemental options */

				case 'F':
					sscanf (&argv[i][2], "%[^/]/%[^/]/%[^/]/%[^/]/%[^/]/%[^/]/%[^/]/%[^/]/%[^/]/%[^/]", varnm[0], varnm[1], varnm[2], varnm[3], varnm[4], varnm[5], varnm[6], varnm[7], varnm[8], varnm[9]);
					break;
				case 'S':
					suppress = TRUE;
					if (argv[i][2] == 'r') reverse = TRUE;
					break;
				default:
					error = TRUE;
					GMT_default_error (argv[i][1]);
					break;
			}
		}
		else
			n_files++;
	}

	if (argc == 1 || GMT_give_synopsis_and_exit) {
		fprintf (stderr, "nc2xy %s - Converting netCDF column file(s) to ASCII xy data\n\n", GMT_VERSION);
		fprintf( stderr, "usage: nc2xy <files> [-F<var1>/<var2>/...] [-S[r]] [-V] > xyfile\n");

		if (GMT_give_synopsis_and_exit) exit (EXIT_FAILURE);

		fprintf (stderr, "\n\t<files> is one or more netCDF files to convert\n");
		fprintf (stderr, "\n\tOPTIONS:\n");
		fprintf (stderr, "\t-F Specify variables to be extracted (up to %d)\n", NVAR);
		fprintf (stderr, "\t-S Suppress records with NaN values [Default prints all nodes]\n");
		fprintf (stderr, "\t   Append r to reverse the suppression (only output records with NaNs)\n");
		GMT_explain_option ('V');
		GMT_explain_option ('.');
		exit (EXIT_FAILURE);
	}

	if (n_files == 0) {
		fprintf (stderr, "%s: GMT SYNTAX ERROR:  Must specify at least one input file\n", GMT_program);
		error++;
	}

	if (error) exit (EXIT_FAILURE);

	GMT_put_history (argc, argv);	/* Update .gmtcommands4 */

#ifdef SET_IO_MODE
	GMT_setmode (GMT_OUT);
#endif
	GMT_io.binary[GMT_OUT] = FALSE;

	for (k = 1; k < argc; k++) {
		if (argv[k][0] == '-') continue;	/* Skip the options */

		/* Open netCDF file */

		nc_nopipe (argv[k]);
		if (nc_open (argv[k], NC_NOWRITE, &ncid)) {
			fprintf (stderr, "%s: Error opening file %s\n", GMT_program, argv[k]);
			exit (EXIT_FAILURE);
		}

		if (gmtdefs.verbose) fprintf (stderr, "%s: Working on file %s\n", GMT_program, argv[k]);

		/* Determine IDs of requested variables; take first two if none given */

		for (n_out = 0; n_out < NVAR && varnm[n_out][0]; n_out++)
			check_nc_status (nc_inq_varid (ncid, varnm[n_out], &varid[n_out]));

		if (n_out == 0) {
			n_out = 2;
			varid[0] = 0;
			varid[1] = 1;
		}

		/* Get further variable attributes */

		n_total = -1;
		for (i = 0; i < n_out; i++) {
			check_nc_status (nc_inq_varndims (ncid, varid[i], &ndims));
			if (ndims != 1) {
				fprintf (stderr, "%s: Variable %s in not 1-dimensional\n", GMT_program, varnm[i]);
				exit (EXIT_FAILURE);
			}
			check_nc_status (nc_inq_vardimid (ncid, varid[i], &dimid));
			check_nc_status (nc_inq_dimlen (ncid, dimid, &len));
			if (n_total < 0)
				n_total = len;
			else if (n_total != (int)len) {
				fprintf (stderr, "%s: Variable %s has different length than others\n", GMT_program, varnm[i]);
				exit (EXIT_FAILURE);
			}
			if (nc_get_att_double (ncid, varid[i], "scale_factor", &scale_factor[i])) scale_factor[i] = 1.0;
			if (nc_get_att_double (ncid, varid[i], "add_offset", &add_offset[i])) add_offset[i] = 0.0;
			if (nc_get_att_double (ncid, varid[i], "_FillValue", &missing_value[i]) &&
			    nc_get_att_double (ncid, varid[i], "missing_value", &missing_value[i])) missing_value[i] = GMT_d_NaN;
		}

		/* Load data record by record and scale as required */

		for (j = 0; j < (size_t)n_total; j++) {
			skip = FALSE;
			for (i = 0; i < n_out; i++) {
				check_nc_status (nc_get_var1_double (ncid, varid[i], &j, &out[i]));
				if (out[i] == missing_value[i])
					out[i] = GMT_d_NaN;
				else {
					out[i] *= scale_factor[i];
					out[i] += add_offset[i];
				}
				if (suppress && GMT_is_dnan (out[i])) {
					skip = TRUE;
					continue;
				}
			}
			if (skip == reverse)
				GMT_output (GMT_stdout, n_out, out);
			else
				n_suppressed++;
		}
	}

	if (gmtdefs.verbose) fprintf (stderr, "%s: %d values extracted\n", GMT_program, n_total - n_suppressed);
	if (n_suppressed && gmtdefs.verbose) {
		if (reverse)
			fprintf (stderr, "%s: %d finite values suppressed\n", GMT_program, n_suppressed);
		else
			fprintf (stderr, "%s: %d NaN values suppressed\n", GMT_program, n_suppressed);
	}

	GMT_end (argc, argv);

	exit (EXIT_SUCCESS);
}
