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

				READ.C
				Main routine that calls format-specific read routines.

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 <limits.h>
#include <assert.h>
#include <math.h>
#include <unistd.h>
/* #include <string.h> */
#include <memory.h>
#include <errno.h>

#include "gpk_std.h"
#include "gpklib/ieee754.h"
#include "gpklib/NaN.h"
#include "gpklib/image.h"
#include "gpkio.h"
#include "gpklib.h"
#include "gpklib/err.h"
#include "gpklib/innerloop2.h"
#include "rbfile.h"
#include "internals.h"
#include "gpklib/assert.h"

#define D	if(0)


#define N_READERS 8

struct reader_s	{
	char * (*reader)(struct multi_image *rv, RBFILE& s, BOOL header_only);
	C char *name;
	} reader[N_READERS] = {
		{getdata_fits, "FITS"},
		{getdata_ascii, "GPK_ASCII"},
		{getdata_SIG, "SIG"},
		{getdata_sphere, "SPHERE"},
		{getdata_HTK, "HParam"},
		{getdata_focas, "FOCAS"},
		{getdata_ATTSSW, "ATTSSW"},
		{getdata_EST, "EST"}
		};



LOCAL char * cmalloc(int x) { return (char *)malloc(x);}



GLOBAL BOOL minmax_strict = FALSE;

LOCAL BOOL tailmatch(C char *p, C char *q)
{
 C int slp = strlen(p);
 C int slq = strlen(q);
 return slp>=slq && strcmp(&p[slp-slq], q)==0;
}


LOCAL C char *is_Z_name(C char *p)
{
 assert(p);
 if(tailmatch(p, ".Z"))
	return "zcat";
 if(tailmatch(p, ".gz"))
	return "zcat";
 if(tailmatch(p, ".bz2"))
	return "bzcat";
 return FALSE;
}


LOCAL FILE *zcat_pipe(C char *name, C char *uncompressor)
{
 FILE *rv;
 char *cmdbuf = cmalloc(strlen(uncompressor) + 1 + strlen(name) + 1);
 assert(cmdbuf);

 strcpy(cmdbuf, uncompressor);
 strcat(cmdbuf, " ");
 strcat(cmdbuf, name);

 rv = popen(cmdbuf, "rb");
 free(cmdbuf);
 return rv;
}


char *gpkio_errmsg(C RBFILE &s)
{
 return strdup(s.ferror() ? "Read error" : "File truncated");
}


LOCAL C char *suffixes[] = {"", ".Z", ".gz", 0};
C static int MaxSuffixLen = 3;

struct multi_image readfile(C char *name, BOOL header_only)
{
 FILE *InStream = 0;
 struct multi_image rv;
 BOOL pipe_in_use = FALSE;

 D fprintf(stderr, "libgpkio: readfile %s\n", name);

 multi_image_empty(&rv);

 BOOL use_stdin = FALSE;
 char *name_suf = cmalloc(strlen(name)+MaxSuffixLen+1);
 if(name[0] != '-') {
	C char **p;
	assert(name_suf);
	for(p=suffixes;*p;p++)	{
		strcpy(name_suf, name);
		strcat(name_suf, *p);
		if(access(name_suf, R_OK)==0)
			break;
		}
 	if(!*p)	{
		free(name_suf);
		fprintf(stderr, "readfile: can't find file, even compressed: %s\n", name);
		return rv;
		}
 	}
 else	{
	use_stdin = TRUE;
	strcpy(name_suf, name);
	}

 C char *uncompressor = is_Z_name(name_suf);
 if(!uncompressor && use_stdin)
	InStream = stdin;
 else if(uncompressor && use_stdin)
	pipe_in_use = (InStream = zcat_pipe("-", uncompressor))!=0;
 else if(!uncompressor)
	InStream = fopen(name_suf, "rb");
 else
	pipe_in_use = (InStream = zcat_pipe(name_suf, uncompressor))!=0;

 if(!InStream)	{
	fprintf(stderr, "ERR: Cannot open %s: %s",
			name_suf, strerror(errno));
	free(name_suf);
	return rv;
	}

 RBFILE s(InStream);

 BOOL success = FALSE;
 int i;
 char *error[N_READERS];
 for(i=0; i<N_READERS; i++)
	 error[i] = NULL;
 for(i=0; i<N_READERS; i++)	{
	assert(rv.n_image == 0);
	D fprintf(stderr, "Trying to interpret as %s...", reader[i].name);
	error[i] = (*reader[i].reader)(&rv, s, header_only);
 	assert(rv.n_image <= NPL);
	if(!error[i]) {
		D fprintf(stderr, "OK\n");
		success = TRUE;
		break;
		}
	else {
		D fprintf(stderr, "Error=%s\n", error[i]);
		}
	}
 if(!success)	{
	for(i=0; i<N_READERS; i++)	{
		if(error[i])	{
			fprintf(stderr, "WARN: %s: %s\n",
					name_suf, error[i]);
			free(error[i]);
			error[i] = 0;
			}
		}
	multi_image_empty(&rv);
	}

 assert(rv.n_image>=0 && rv.n_image <= NPL);
 if(rv.n_image <= 0)
	fprintf(stderr, "WARN: read.c: Nothing done\n");

 assert(rv.n_image>=0 && rv.n_image <= NPL);
 for(i=0; i<rv.n_image; i++)
	rv.image[i].prop->add("_NAME", name_suf, name);

 assert(rv.n_image>=0 && rv.n_image <= NPL);
 free(name_suf);

 if(pipe_in_use)
 	pclose(InStream);
 else if(use_stdin)
 	;
 else
 	fclose(InStream);
 assert(rv.n_image>=0 && rv.n_image <= NPL);
 multi_image_check(&rv);

 return rv;
}


