/*****************************************************************************

				ASCII_READ.C
				Reads in GPK ASCII IMAGE format data files.

Copyright (C) 2002 Greg Kochanski, gpk@pribble.com .

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; either version 2 of the License, or
(at your option) any later version.

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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <math.h>

#include "gpklib/ieee754.h"
#include "gpklib.h"
#include "gpklib/image.h"
#include "gpklib/NaN.h"
#include "rbfile.h"
#include "gpklib/assert.h"
#include "internals.h"
#include "rw_misc.h"
#include "read_data.h"

#define D if(0)

char *getdata_ascii(struct multi_image *rv, RBFILE& s, BOOL header_only)
{
 char err[1024];
 struct image * p = &rv->image[0];

 s.rewind();
 multi_image_empty(rv);
 assert(rv->n_image == 0);

 p->prop = new proplist;
 assert(p->prop);

 char hdr_rec[10000];
 int hdr_line = 0;
 while(1)	{
	hdr_line++;
	if(!s.fgets(hdr_rec, sizeof(hdr_rec)))	{
		multi_image_destr(rv);
		sprintf(err, "not ascii-image: can't read header, line %d.",
				hdr_line);
		return strdup(err);
		}
	D fprintf(stderr, "DBG: s.fgets done: {%s}\n", hdr_rec);

	if(hdr_rec[0] == '#')
		continue;

	if(hdr_rec[0] == '\0')	{
		multi_image_destr(rv);
		sprintf(err, "not ascii-image: null header line %d.",
				hdr_line);
		return strdup(err);
		}

	if(!chomp_newline(hdr_rec) < 0)	{
		multi_image_destr(rv);
		sprintf(err, "not ascii-image: header missing newline "
				"(line %d too long or null?)", hdr_line);
		return strdup(err);
		}

	if(hdr_rec[0] == '\0')
		break;

	proplist pl = avparse(hdr_rec);
	if(pl.get(""))	{
		multi_image_destr(rv);
		D fprintf(stderr, "DBG: ascii_read.c: fail on {%s}\n", hdr_rec);
		property *pp = pl.get("");
		sprintf(err, "not ascii-image: can't parse header (line %d): %s(%s).",
				hdr_line,
				pp->val&&*pp->val ? pp->val : "unknown problem",
				pp->comment?pp->comment:"");
		return strdup(err);
		}

	property *tt;		/* Any comment is attached to a value. */
	char *comment = strdup(pl.gets("_COMMENT", ""));
	if(comment && *comment)
		add_append_property(p->prop, "_COMMENT", comment, 0);
	if(comment)
		free(comment);
	pl.add("_COMMENT", (char *)0);
	for(tt=pl.first; tt; tt=tt->next)	{
		if(!*tt->attr || !tt->val)
			continue;
		if(pl.get(tt->attr) != tt)
			continue;
		D fprintf(stderr, "attr=%s val=%s com=%s\n", tt->attr, tt->val, tt->comment?tt->comment:"<nil>");
		add_append_property(p->prop, tt->attr, tt->val, tt->comment);
		}
	}
 assert(rv->n_image == 0);


 if(p->prop->get("NAXIS") && p->prop->geti( "NAXIS", -1) != 2)	{
	fprintf(stderr, "INFO: can't handle ascii Naxis=%s, not 2\n", p->prop->gets( "NAXIS", ""));
	multi_image_destr(rv);
	assert(0);
	}

 p->nlines = p->prop->geti("NAXIS2", -1);
 if(p->nlines <= 0)	{
	sprintf(err, "INFO: not ascii bad NAXIS2=%s", p->prop->gets( "NAXIS2", ""));
	multi_image_destr(rv);
	return strdup(err);
	}

 p->npts = p->prop->geti("NAXIS1", -1);
 if(p->npts <= 0)	{
	sprintf(err, "not ascii bad NAXIS1=%s", p->prop->gets( "NAXIS1", ""));
	multi_image_destr(rv);
	return strdup(err);
	}

 assert(rv->n_image == 0);
 D fprintf(stderr, "Committed to ascii_image\n");
 s.commit();		/* Toss out the buffer. */

 if(!header_only)	{
	char * fail = 0;
	C int bitpix = p->prop->geti("BITPIX", 0);
	if(bitpix != 0)
		fail = gpkio_read_in_data(s, p, p->nlines, p->npts, bitpix, p->prop->getl("BLANK"), NETWORK_ORDER);
	else
		fail = gpkio_read_in_data_ascii(s, p);

	if(fail)	{
		multi_image_destr(rv);
		sprintf(err, "not ascii image: read fails after header: %s.", fail);
		free(fail);
		return strdup(err);
		}
	}
 p->xscale = p->prop->getd("xscale", 1.0);
 p->xscale = p->prop->getd("CDELT1", p->xscale);	/* Preferred. */
 p->yscale = p->prop->getd("yscale", 1.0);
 p->yscale = p->prop->getd("CDELT2", p->yscale);	/* Preferred. */
 p->zscale = p->prop->getd("zscale", 1.0);
 p->zscale = p->prop->getd("BSCALE", p->zscale);	/* Preferred. */
 p->zshift = p->prop->getd("zshift", 0.0);
 p->zshift = p->prop->getd("BZERO", p->zshift);		/* Preferred. */

 D fprintf(stderr, "zscale=%g from %s or %s\n", p->zscale,
	p->prop->gets("zscale", "<nil>"), p->prop->gets("BSCALE", "<nil>"));
 D fprintf(stderr, "zshift=%g from %s or %s\n", p->zshift,
	p->prop->gets("zshift", "<nil>"), p->prop->gets("BZERO", "<nil>"));

 p->xcenter = p->prop->getd("CRVAL1", 0.0)
		+ p->xscale*(0.5*(p->npts-1) - (p->prop->getd("CRPIX1", 1.0)-1.0));
 p->ycenter = p->prop->getd("CRVAL2", 0.0)
		+ p->yscale*(0.5*(p->nlines-1) - (p->prop->getd("CRPIX2", 1.0)-1.0));
 D fprintf(stderr, "ycenter=%g from v=%g sc=%g pix=%g rows=%d\n",
		p->ycenter, p->prop->getd("CRVAL2", 0.0), p->yscale,
		p->prop->getd("CRPIX2", 1.0), p->nlines);

 if(p->prop->get("BUNIT"))
	p->prop->add("zunits", p->prop->gets("BUNIT", "???"));
 if(p->prop->get("CTYPE1"))
	p->prop->add("xunits", p->prop->gets("CTYPE1", "???"));
 if(p->prop->get("CTYPE2"))
	p->prop->add("yunits", p->prop->gets("CTYPE2", "???"));
 if(p->prop->get("CROTA1"))
	p->prop->add("angle", p->prop->gets("CROTA1", "???"));
 p->i_noise = p->prop->getd("I_NOISE", 0.0);
 p->prop->add("_FILETYPE", "GPK ASCII image", "Header & multicolumn ascii file");
 gpkio_date_fix(p->prop);
 assert(rv->n_image == 0);
 rv->n_image++;
 assert(rv->n_image == 1);

 return 0;
}
