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

				FOCAS_READ.C
				Reads Tyson FOCAS format 2-dimensional image 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 <assert.h>
#include <math.h>
#include <string.h>
#include <time.h>

#include "gpk_std.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)

LOCAL short read_focas_short(RBFILE *fp)
{
 unsigned tmp = ((unsigned)(fp->fgetc()))<<8;
 tmp |= (unsigned)(fp->fgetc());
 return (short)tmp;
}


LOCAL long read_focas_long(RBFILE *fp)
{
 long rv;
 rv = ((unsigned)(fp->fgetc()))<<8;
 rv |= (unsigned)(fp->fgetc());
 rv <<= 16;
 rv |= ((unsigned)(fp->fgetc()))<<8;
 rv |= (unsigned)(fp->fgetc());
 return rv;
}


LOCAL float read_focas_float(RBFILE *fp)
{
 float f;
 fp->fread((char *)&f, sizeof(float), 1);
 return f;
}


LOCAL char nullmap(int x)
{
 return x==(-1) ? '\0' : (char)x;
}




char * getdata_focas(struct multi_image *rv, RBFILE& s, BOOL header_only)
{
 struct image * p = &rv->image[0];
 char fl[33], com[257], errbuf[512];
 int i;
 short bytepix;
 long blank;
 float fminval, fmaxval;

 s.rewind();
 multi_image_empty(rv);
 {
 C short blksiz = read_focas_short(&s);	/* blksiz */
 if(blksiz%2880 != 0)	{
	sprintf(errbuf, "not FOCAS: blksiz=%d", blksiz);
	return strdup(errbuf);
	}
 }
 C short bitpix = read_focas_short(&s);
 C short naxis = read_focas_short(&s);
 if(naxis != 2)	{
	sprintf(errbuf, "not FOCAS: naxis=%d", naxis);
	return strdup(errbuf);
	}
 assert(naxis == 2);
 C int cols = read_focas_short(&s);
 C int rows = read_focas_short(&s);
	/* 10 */
 D	fprintf(stderr, "rows=%d, cols=%d\n", rows, cols);
 if(rows<=0 || cols<=0)	{
	sprintf(errbuf, "not FOCAS: rows=%d, cols=%d", rows, cols);
	return strdup(errbuf);
	}
 D fprintf(stderr, "rowcol.\n");
 read_focas_short(&s);	/* dflags */
 read_focas_short(&s);	/* maptyp */
 read_focas_short(&s);	/* bunit */
 read_focas_short(&s);	/* ctype1 */
 read_focas_short(&s);	/* ctype2 */
	/* 20 */
 assert(sizeof(float) == sizeof(long));
 fmaxval = read_focas_float(&s);
 fminval = read_focas_float(&s);
	/* 28 */
 C float b_scale = read_focas_float(&s);
 C float b_zero = read_focas_float(&s);
 for(i=0;i<32;i++)
	s.fgetc();
 blank = read_focas_long(&s);
	/* 72 */
 {
 char simple = s.fgetc();
 char aftersimple = s.fgetc();
 if(simple!='T' && (aftersimple!=' ' || aftersimple!='\0'))	{
	sprintf(errbuf, "not FOCAS: simple= %x %x",  simple, aftersimple);
	return strdup(errbuf);
	}
 }
 bytepix = read_focas_short(&s);
 if((bytepix!=1 && bytepix!=2 && bytepix!=4) || abs(bitpix)!=8*bytepix)	{
	sprintf(errbuf, "not FOCAS: bad bytepix=%d or bitpix=%d", bytepix, bitpix);
	return strdup(errbuf);
	}
 s.fgetc(); s.fgetc(); s.fgetc(); s.fgetc();
 s.fgetc(); s.fgetc(); s.fgetc(); s.fgetc();

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

D	fprintf(stderr, "hdr84.\n");

	/* 84 */
 for(i=0;i<12;i++)	/* dummy */
	s.fgetc();
	/* 96 */
 for(i=0;i<32;i++)	/* Object.*/
	fl[i] = nullmap(s.fgetc());
 fl[i] = '\0';
 if(fl[0] != '\0')	{
	D fprintf(stderr, "OBJECT: %s\n", fl);
	chomp_whitespace(com);
	p->prop->add("OBJECT", fl);
	}
	/*  128 */
D	fprintf(stderr, "label=%s\n", fl);





 for(i=0;i<32;i++)
	com[i] = nullmap(s.fgetc());
 com[i] = '\0';
 if(com[0] != '\0')	{
	D fprintf(stderr, "Origin: %s\n", com);
	chomp_whitespace(com);
	p->prop->add("ORIGIN", com);
	}

 for(i=0;i<32;i++)
	com[i] = nullmap(s.fgetc());
 com[i] = '\0';
 if(com[0] != '\0')	{
	D fprintf(stderr, "Date: %s\n", com);
	chomp_whitespace(com);
	p->prop->add("DATE", com);
	}

 for(i=0;i<32;i++)
	com[i] = nullmap(s.fgetc());
 com[i] = '\0';
 if(com[0] != '\0')	{
	D fprintf(stderr, "Observer: %s\n", com);
	chomp_whitespace(com);
	p->prop->add("OBSERVER", com);
	}

 for(i=0;i<32;i++)
	com[i] = nullmap(s.fgetc());
 com[i] = '\0';
 if(com[0] != '\0')	{
	D fprintf(stderr, "Nextpic: %s\n", com);
	chomp_whitespace(com);
	p->prop->add("NEXTPIC", com);
	}

 for(i=0;i<256;i++)
	com[i] = nullmap(s.fgetc());
 com[i] = '\0';
 if(com[0] != '\0')	{
	D fprintf(stderr, "Comment: %s\n", com);
	chomp_whitespace(com);
	p->prop->add("COMMENT", com);
	}
D fprintf(stderr, "hdr end.\n");


D fprintf(stderr, "alloc checked.\n");
 rv->n_image++;
 image_setzscale(p, b_scale, "ARBs", b_zero);
 if(bytepix==1 || bytepix==2)
	p->prop->add("BLANK", SHRT_NAN);
 else if(bytepix == 4)
	p->prop->add("BLANK", LONG_NAN);

 p->prop->add("DATAMAX", fmaxval);
 p->prop->add("DATAMIN", fminval);
 p->prop->add("type", "Intensity");
 p->xscale = 1.0;
 p->yscale = 1.0;
 p->xcenter = 0.0;
 p->ycenter = 0.0;
 p->constr_time = time(0);
 p->i_noise = bitpix>0 ? fabs(b_scale)*10.0 : 1.0;
 p->prop->add("xunits", "pixels");
 p->prop->add("yunits", "pixels");
 p->prop->add( "zunits", "ADUs");
 p->prop->add("_FILETYPE", "FOCAS", "Tyson and Valdez");
 p->prop->add("BITPIX", bitpix);
 p->prop->add("BYTEPIX", bytepix);
 image_addlabel(p, fl);

 /* We know what type of file we have,
	and that the header is correctly understood. */

 s.commit();		/* Toss out the buffer. */

 if(!header_only)	{
	D fprintf(stderr, "INFO: focas_read: blank=%ld\n", blank);
	char *fail = gpkio_read_in_data(s, &rv->image[0], rows, cols, bitpix, blank, LOCAL_ORDER);
	if(fail)	{
		multi_image_destr(rv);
		sprintf(errbuf, "not FOCAS: read fails after header: %s.", fail);
		free(fail);
		return strdup(errbuf);
		}
	}

 return 0;
}


