#include <stdio.h>
#include <ctype.h>
#include "bait.h"
#include "pf.h"
#include "header.h"
#include "fits.h"


	/* get a header-line value from a pseudo-FITS file, or from a true FITS
	   file. The syntax is:

	     picksym  [file=name]  [default=xxx]  [nostrip]  symbol  [quiet]
	                  [stanza=n] [nochop]

	   where 'file' is the file to look at (default is the
	   ait.config file).  The program prints out the value of the
	   symbol, if found, and exits with code 0; if the symbol is not found,
	   but 'default=xxx' is specified, then 'xxx' is printed out and 0
	   returned.  If the symbol is not found and no default is given, then
	   a message is printed to stderr and a non-zero exit code is returned.
	   If 'quiet' is specified, an error message is not printed if the
	   given symbol cannot be found in the file.

	   Unless the 'stanza' keyword is given, only the first stanza of a 
	   request file is searched; with it, any stanza can be specified.
	   For true FITS files, of course, there is only one stanza.

	   Note that symbols which are surrounded by apostrophes (i.e. string
	   symbols) will have their apostrophes removed unless the
	   'nostrip' keyword is given; in that case, they will be left as is. 

	   By default, the program chops off all comments at the end of 
	   a FITS header line.  The 'nochop' option returns a value with
	   the end-of-line comments included.

	   Also note that COMMENTs are handled separately, but in a rational
	   fashion: saying

	            picksym file=foo.rqs comment

	   will print out ALL of the comment lines in the first stanza of 
	   file foo.rqs.  */

/*
 * Added "nochop" option, which does NOT chop off any comments from the end of 
 *   a FITS keyword value.  In other words, if the header line is 
 *
 *             EXPTIME =  20.0     / a short exposure
 *   
 *   then the default behavior is for keyword "EXPTIME" is to return 20.0;
 *   but if "nochop" is given, the the program will return
 *   "20.0     / a short exposure".
 *
 *   MWR  4/6/2001
 */

#define CARD_LEN       80	/* length of header lines in true FITS */

static int pseudo_fits( /* char *filename, *sym, *def, int strip_flag, 
                          quiet_flag, def_flag, chop_flag */ );
static int true_fits( /* char *filename, *sym, *def, int strip_flag, 
                          quiet_flag, def_flag, chop_flag */ );
static void strip_spaces( /* char *str */ );
static void strip_quotes( /* char *str */ );
static void chop_comment( /* char *str */ );
char *progname = "picksym";

main(argc, argv)
int argc;
char *argv[];
{
	int i, def_flag, strip_flag, quiet_flag, stanza, type, ret;
	int chop_flag;
	char filename[100], sym[100], def_str[100];
	char *gotit, *find();

	if (argc < 2) {
		fprintf(stderr, "usage: picksym [file=name] [default=xxx] [nochop] [nostrip] [stanza=n] symbol\n");
		exit(1);
	}

	strcpy(filename, CONFIG_FILE);
	strcpy(sym, "");
	def_flag = 0;
	strip_flag = 1;
	quiet_flag = 0;
	chop_flag = 1;
	stanza = 1;

	for (i = 1; i < argc; i++) {
		if ((gotit = find("file", argv[i])) != NULL) {
			strcpy(filename, gotit);
			continue;
		}
		if ((gotit = find("default", argv[i])) != NULL) {
			strcpy(def_str, gotit);
			def_flag = 1;	
			continue;
		}
		if (keyword("nostrip", argv[i])) {
			strip_flag = 0;
			continue;
		}
		if (keyword("quiet", argv[i])) {
			quiet_flag = 1;
			continue;
		}
		if (keyword("nochop", argv[i])) {
			chop_flag = 0;
			continue;
		}
		if ((gotit = find("stanza", argv[i])) != NULL) {
			if (sscanf(gotit, "%d", &stanza) != 1) {
				fprintf(stderr, "bad value for stanza: ..%s..\n", argv[i]);
				exit(1);
			}
			continue;
		}
		strcpy(sym, argv[i]);
	}
	if (strcmp(sym, "") == 0) {
		fprintf(stderr, "usage: picksym [file=name] [default=xxx] [nostrip] symbol\n");
		exit(1);
	}
	for (i = 0; i < strlen(sym); i++)
		sym[i] = toupper(sym[i]);

	if ((type = fits_file_type(filename)) == NOT_FITS) {
		fprintf(stderr, "file %s is not FITS-like\n", filename);
		exit(1);
	}

	if (type == PSEUDO_FITS) 
		ret = pseudo_fits(filename, sym, strip_flag, quiet_flag, 
					def_flag, def_str, stanza, chop_flag);
	else
		ret = true_fits(filename, sym, strip_flag, quiet_flag, 
					def_flag, def_str, chop_flag);

	exit(ret);
}

	/* do the picking from a true FITS file */

static int
true_fits(filename, sym, strip_flag, quiet_flag, def_flag, def_str, chop_flag)
char *filename, *sym, *def_str;
int strip_flag, quiet_flag, def_flag, chop_flag;
{
	int i, count;
	unsigned nrow, ncol;
	char *p, val[CARD_LEN + 1], str[PF_LEN + 1];
	FITS_HANDLE fh;

	if ((fh = fits_open(filename, "r", &nrow, &ncol)) < 0) {
		fprintf(stderr, "can't open FITS file %s\n", filename);
		exit(1);
	}

	/* handle COMMENT lines in a special way */
	if (strcmp(sym, "COMMENT") == 0) {
		count = 0;
		for (i = 1; ; i++) {
			if ((p = fits_get_headerline(fh, i)) == NULL)
				break;
			if (strncmp(p, "COMMENT", 7) == 0) {
				count++;
				strncpy(val, p, CARD_LEN);
				val[CARD_LEN] = '\0';
				printf("%s\n", val);
			}
		}
		fits_close(fh);
		if (count == 0) {
			if (!quiet_flag)
				fprintf(stderr, "can't find any comments in file %s\n", filename);
			return(1);
		}
		else {
			return(0);
		}
	}

	if (fits_get_symbol(fh, sym, val) != FITS_PASS) {
		fits_close(fh);
		if (def_flag == 1) {
			printf("%s\n", def_str);
			return(0);
		}
		else {
			if (!quiet_flag)
				fprintf(stderr, "can't find keyword %s in file %s\n", 
						sym, filename);
			return(1);
		}
	}

	if (chop_flag == 1) {
		chop_comment(val);
	}
	
	if (strip_flag == 1) {
		strip_spaces(val);
		if ((pf_valtype(val) == PF_STRING) && (pf_valtostr(val, str) == 0)) {
			printf("%s\n", str);
		}
		else
			printf("%s\n", val);
	}
	else
		printf("%s\n", val);

	fits_close(fh);
	return(0);
}


	/* do the picking from a pseudo-FITS file */

static int
pseudo_fits(filename, sym, strip_flag, quiet_flag, def_flag, def_str, stanza, 
		  chop_flag)
char *filename, *sym, *def_str;
int strip_flag, quiet_flag, def_flag, stanza, chop_flag;
{
	int i;
	char val[PF_LEN + 1], str[PF_LEN + 1];
	pf_handle pf_in;
	
	if ((pf_in = pf_open(filename, stanza, PF_EXIST)) < 0) {
		fprintf(stderr, "can't open file %s stanza %d, or not a pseudo-FITS file\n", filename, stanza);
		exit(1);
	}

	/* handle COMMENTs in a slightly different manner than the rest */
	if (strcmp(sym, "COMMENT") == 0) {
		i = 0;
		while (pf_getcomment(pf_in, str) != NULL) {
			printf("%s", str);
			i++;
		}
		pf_close(pf_in);
		if (i == 0) {
			if (!quiet_flag)
				fprintf(stderr, "can't find any comments in file %s\n", filename);
			return(1);
		}
		else {
			return(0);
		}
	}

	if (pf_getval(pf_in, sym, val) == NULL) {
		pf_close(pf_in);
		if (def_flag == 1) {
			printf("%s\n", def_str);
			return(0);
		}
		else {
			if (!quiet_flag)
				fprintf(stderr, "can't find keyword %s in file %s\n", 
						sym, filename);
			return(1);
		}
	}
	else {
		if (chop_flag == 1) {
			chop_comment(val);
		}

		if (strip_flag != 0) {
			/* try stripping white space, apostophes, etc. */
			strip_spaces(val);
			if ((pf_valtype(val) == PF_STRING) && (pf_valtostr(val, str) == 0)) {
				printf("%s\n", str);
			}
			else
				printf("%s\n", val);
		}
		else {
			printf("%s\n", val);
		}
	}

	pf_close(pf_in);
	return(0);
}

	/* strip off any leading/trailing white space from the given string */

static void
strip_spaces(str)
char *str;
{
	int i;
	char buf[PF_LEN + 1], *p;

	p = str;
	while ((*p == ' ') || (*p == '\t'))
		p++;

	for (i = 0; *p != '\0'; p++) {
		buf[i++] = *p;
	}
	buf[i] = '\0';

	for ( ; (buf[i - 1] == ' ') || (buf[i - 1] == '\t'); i--)
		;
	buf[i] = '\0';

	strcpy(str, buf);
}


/****************************************************************************
 * PROCDURE: chop_comment
 *
 * DESCRIPTION: Given the contents of a FITS header line, chop off any
 *              end-of-line comments.  The comments are signalled
 *              by the presence of a FITS_CMT_CHAR character, and 
 *              continue from its position rightwards to the end of 
 *              the line.
 *
 *              The given string is modified by this function.
 *
 * RETURNS: 
 *    nothing
 */

static void
chop_comment(str)
char *str;
{
	int i, found;

	/* is there a comment character in the string? */
	found = 0;
	for (i = 0; i < PF_LEN; i++) {
		if (str[i] == '\0') {
			break;
		}
		if (str[i] == COMMENT_CHAR) {
			found = 1;
			break;
		}
	}

	/* 
	 * if there was a comment character, replace it with '\0' 
	 * so that the value of the keyword will not include the 
	 * comment.
	 */
	if (found == 1) {
		str[i] = '\0';
	}
}

