/*===========================================================================
  Copyright (C) 1995-2009 European Southern Observatory (ESO)
 
  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 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*+++++++++++++++++++++ Module MIDFCTB +++++++++++++++++++++++++++++++++++++++
.LANGUAGE   C
.IDENTIFICATION  Module MIDFCTB.C
.AUTHOR   Klaus Banse
.KEYWORDS Midas FITS utility routines.
.ENVIRONMENT VMS and UNIX
.COMMENTS
holds the FITS input routines: MID_fitstest, MID_fitsin, MID_fitsrdm, MyPut

.VERSION 
 090326		last modif
------------------------------------------------------------------------*/
 
#include <fileexts.h>
#include <fsydef.h>
#include <errext.h>
#include <proto_st.h>
#include <proto_tbl.h>
#include <proto_dio.h>

#include <osyparms.h>             /* General data definitions       */
#include <fitsfmt.h>             /* General data definitions       */
#include <fitsdef.h>             /* Basic FITS definitions         */
#include <fitskwt.h>             /* Table Extension definitions  */
#include <computer.h>            /* computer specific constants    */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


static char  *dataout_ptr;	/* used in MyPut */
static int   dataout_outtyp;
static int   eco, elo, edi;			/* for ERRO_CONT, _LOG, _DISP */

/*

*/

#ifdef __STDC__
void reset_ERRO(int fid)
#else
void reset_ERRO(fid)
int     fid;
#endif

{
ERRO_CONT = eco;        /* reset ERROR environment again */
ERRO_LOG = elo;
ERRO_DISP = edi;

dclose(fid);		/* close FITS file */
}




#ifdef __STDC__
int MID_fitstest(char *fname)
#else
int MID_fitstest(fname)
char      *fname;       /* IN: name of input FITS file */
#endif

{
char    work[400], *nampntr;

int     fidcount, fid, n, kpath, retstat;

extern char DATA_PATH[328];





retstat = -1; 
kpath = fidcount = n = 0;
nampntr = fname;
work[0] = '^';


open_file:
if ((fid = dopen(nampntr,READ,'S',0)) < 0)     /* try to open FITS file */
   {
   if (fidcount < 4)
      {
      (void) strncpy(work,&DATA_PATH[n],80);
      if (work[0] != '^')
         {
         work[80] = ' ';
         kpath = CGN_INDEXC(work,' ');
         (void) strcpy(&work[kpath],fname);          /* use new path */
         nampntr = work;
         fidcount ++;
         n += 80;
         goto open_file;
         }
      }
   return retstat;
   }


if (drinit() != FITS)           /* check file format */
   retstat = -2;
else
   retstat = 0;

dclose(fid);

return retstat;
}
/*

*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.AUTHOR     
K. Banse   ESO/IPG
.KEYWORDS   
FITS prime data matrix, decode, read
.PURPOSE    
Read prime data matrix in FITS and create a MIDAS bdf-file
.ALGORITHM
Either just read the FITS header to create a corresponding Midas header
in memory 
Or just skip the FITS header to get to the data.
.RETURN     
status       0: OK, -1: cannot open file, -2: wrong format
            -3: no data matrix, -4: bad output name
            -5: unknown FITS extension
---------------------------------------------------------------------*/

#ifdef __STDC__
int MID_fitsin(int flag, char *fname, int extensio, char *bname, 
               char *outbuf, int *mfd, int *info)
#else
int MID_fitsin(flag,fname,extensio,bname,outbuf,mfd,info)
int       flag;		/* IN: option = 0, get type of FITSfile [extension] (d)
				      = 1, get FITS header (a)
				      = 2, get FITS data (b)
				      = 3, skip FITS header (c) */
				      = -1, list all extensions (e)
				      = -2, get extno from extstring (f) */
char      *fname;	/* IN: name of input FITS file */
int       extensio;	/* IN: extension no. (a,d) */
char      *bname;	/* IN: name of output BDF file */
char      *outbuf;	/* IN/OUT: output buffer
			   (a)     return path name if applicable 
			   (b)     pointer to data area to be filled 
			   (c,d,e)     ignored 
			   (f)    EXTNAME string  */
int       *mfd;		/* IN/OUT: MIDAS file no.  
				   output (a), input (b,c) */
int       *info;	/* OUT: info = FITS file type (a,d) 
				       not used (b)
				       fileid from dopen (c)
				       no. of extensions (e)
				       extension no. of EXTNAME (f) */
#endif

{
char    work[400], *nampntr, extlabel[24], temp[400];

int     Mflag, dsize, fidcount, fid, err, kpath, n, type, mfdt, imno;
int     extno, extcount, extrecs;
int     eco, elo, edi;			/* for ERRO_CONT, _LOG, _DISP */
register int  nr;

BFDEF  *bfdefptr, bfdef;
ADEF   *adefptr, adef[MXDIM];
PDEF   *pdefptr, pdef[MXPAR];

struct FCT_STRUCT  *fctpntr;

extern char DATA_PATH[328];




/*
printf("... entering MID_fitsin with flag = %d, name = %s, ext = %d, bname = %s\n",
flag,fname,extensio,bname);
*/


kpath = fidcount = n = 0; 
nampntr = fname;
work[0] = '^';

open_file:
if ((fid = dopen(nampntr,READ,'S',0)) < 0)     /* try to open FITS file */
   {
   if (fidcount < 4)
      {
      (void) strncpy(work,&DATA_PATH[n],80);
      if (work[0] != '^')
         {
         work[80] = ' ';
         kpath = CGN_INDEXC(work,' ');
         (void) strcpy(&work[kpath],fname);          /* use new path */
         nampntr = work;
         fidcount ++;
         n += 80;
         goto open_file;
         }
      }
   return (-1);  
   }


if (drinit() != FITS)		/* check file format */
   {                    /* if not FITS format - exit */
   dclose(fid); 
   return (-2);
   }


eco = ERRO_CONT;
elo = ERRO_LOG;
edi = ERRO_DISP;


/* if flag < 2 we have to get the FITS header in */
/* --------------------------------------------- */
				
if (flag < 2)				/* process flag = -1, 0, 1 */
   {			
   char  *mypntr;
   int  ln0;

   *mfd = mfdt = -1;			/* don't access data yet */
   if (extensio < 0)
      err = outname(bname,0,'y'); /* no extension, we just need a single name */
   else
      err = outname(bname,0,'x'); 
   if (err) 
      {                        /* define output file name + check it */
      dclose(fid);
      return (-4);
      }

   mypntr = malloc((size_t) (sizeof(bfdef)));
   if (mypntr == (char *) 0) return (-5);
   bfdefptr = (BFDEF *) mypntr;

   mypntr = malloc((size_t) (MXDIM*sizeof(adef)));
   if (mypntr == (char *) 0) return (-5);
   adefptr = (ADEF *) mypntr;

   mypntr = malloc((size_t) (MXPAR*sizeof(pdef)));
   if (mypntr == (char *) 0) return (-5);
   pdefptr = (PDEF *) mypntr;

   hdr_init_M(bfdefptr,&adefptr,&pdefptr,0);	/* init internal structure */
   extrecs = 0;


   /* read FITS header, create file (only if flag = 1)  */

   ERRO_CONT = 1;        /* disable SC-error handling   */
   ERRO_LOG = ERRO_DISP = 0;
               /* instead of: ln1 = 1; ln0 = 0; SCECNT("PUT",&ln1,&ln0,&ln0); */

   extcount = 0;
 
   if (flag == 0)			/* we just want info */
      Mflag = -2;
   else	
      Mflag = 1;			/* maybe changed in next section */


   /* for flag = -1, we just loop through all extensions */

   if (flag == -1)
      {
      Mflag = -1;
      type = fitsrhd(mfd,bfdefptr,&dsize,&mfdt,'O','Y',0,Mflag);

      if (type < BFITS)	
         {
         ERRO_CONT = eco;        /* reset again */
         ERRO_LOG = elo;
         ERRO_DISP = edi;
         dclose(fid); 
         return (-2);
         }

      memset((void *)work,32,(size_t)25); work[25] = '\0';
      if (dsize < 1)            /* an empty primary matrix, so look for next */
         {
         (void) strcpy(extlabel,"Empty primary header");
         (void) snprintf(temp,(size_t) 400,"extension[%d] %s - type = %s",
                     extcount,work,extlabel);
         }
      else
         {
         if (type == ATABLE)
            (void) strcpy(extlabel,"Ascii table");
         else if (type == BTABLE)
            (void) strcpy(extlabel,"Binary table");
         else
            (void) strcpy(extlabel,"Image");
         (void) snprintf(temp,(size_t) 400,"extension[%d] %s - type = %s",
                     extcount,work,extlabel);
         }
      SCTPUT(temp);
      extcount ++;
 
     n_loop:  
      (void) fitssxd(dsize,1);              /* skip data matrix */

      hdr_init_M(bfdefptr,&adefptr,&pdefptr,1);    /* init again */
      type = fitsrhd(mfd,bfdefptr,&dsize,&mfdt,'O','Y',0,Mflag);


      if (type == EOFITS)
         {				/* we reached EOF */
         flag = 0;
         *info = extcount;		/* save total no. of extensions */
         goto after_exttypes;		/* continue like the rest */
         }
      else if (type < BFITS)
         {
         if (flag == -1)
            {
            SCTMES(M_BLUE_COLOR,"bad FITS extension ...we skip");
            if (dsize > 0) fitssxd(dsize,0);
            goto n_loop;
            }
         else
            {
            reset_ERRO(fid);
            return (-2);
            }
         }


      if (type == ATABLE)
         (void) strcpy(extlabel,"Ascii table");
      else if (type == BTABLE)
         (void) strcpy(extlabel,"Binary table");
      else if (type == IMAGE)
         {
         if (dsize < 1)            /* an empty header */
            (void) strcpy(extlabel,"Empty header");
         else
            (void) strcpy(extlabel,"Image");
         }
      else
         {
         if (dsize < 1)            /* an empty header */
            (void) strcpy(extlabel,"Empty header");
         else
            (void) strcpy(extlabel,"? ");
         }

      (void) snprintf(temp,(size_t) 400,
                  "extension[%d] EXTNAME: %16.16s - type = %s",
                  extcount,bfdefptr->extname,extlabel);
      SCTPUT(temp);

      extcount ++;
      goto n_loop;
      }

   /* --- end of extension-check loop 
          if all o.k. we meet you at label  after_exttypes:  ---  */



   /* check, if we want an extension of the FITS file */

   if ((flag != -2) && (extensio < 0))	/* No, frame without extension */
      {
      type = fitsrhd(mfd,bfdefptr,&dsize,&mfdt,'O','Y',0,Mflag);

      if (type < -990)			/* 1st look for TCTINI/SCFCRE errors */
         {
         if (type == -998)
            SCTMES(M_RED_COLOR,"problems creating image...");
         else
            SCTMES(M_RED_COLOR,"problems creating table...");
         reset_ERRO(fid);
         return (-9);
         }
      if (type < BFITS)				/* main header */
         {
         reset_ERRO(fid);
         return (-2);
         }

      if (dsize > 0)		/* basic FITS goes to IMAGE type */
         *info = 1;	
      else
         {			/* search for first non-empty header */
         if (flag == 0) Mflag = -1;

         while ( (dsize < 1) && 
                 ((type == BFITS) || (type == IMAGE)) )
            {
            *mfd = -1; mfdt = -1;
            hdr_init_M(bfdefptr,&adefptr,&pdefptr,1);   /* init again */
            type = fitsrhd(mfd,bfdefptr,&dsize,&mfdt,'O','Y',0,Mflag);

            if (type < -990)		/* 1st look for TCTINI/SCFCRE errors */
               {
               if (type == -998)
                  SCTMES(M_RED_COLOR,"problems creating image...");
               else
                  SCTMES(M_RED_COLOR,"problems creating table...");
               reset_ERRO(fid);
               return (-9);
               }
            if (type == EOFITS)
               {
               reset_ERRO(fid);
               return (-6);
               }
            }

         *info = 0;
         if (type == ATABLE)
            *info = 3;
         else if (type == BTABLE)
            *info = 2;
         else if (type == IMAGE)
            *info = 1;
         extcount ++;			/* count extensions */
         }

      extno = 0;			/* ext.no. 0 = main frame */
      goto after_exttypes;
      }


   /* Yes - we do have an extension */

   if (flag != -2) 
      {
      extno = extensio;
      extlabel[0] = '\0';	
      }

   /* we have to find extension with EXTNAME = input string (outbuf) */
   else
      {
      extno = 1000;
      extlabel[16] = '\0';		/* extensions have max. 16 chars */

      if (outbuf[0] == '"')
         {
         for (nr=0; nr<16; nr++)	
            {
            extlabel[nr] = outbuf[nr+1];
            if (extlabel[nr] == '"')
               {
               extlabel[nr] = '\0';
               break;
               }
            }
         }
      else
         {
         for (nr=0; nr<16; nr++)
            {
            extlabel[nr] = outbuf[nr];
            if (extlabel[nr] == ' ')
               {
               extlabel[nr] = '\0';
               break;
               }
            }
         }
      CGN_UPSTR(extlabel);
      }

 
   /* read very first FITS header */

   if (Mflag == 1) 
      Mflag = 101;		/* mark possible empty file for `fitsrhd' */

   if ((extno > 0) && (Mflag == 101))
      n = Mflag + 200;		/* now 301 */ 
   else
      n = Mflag;

   type = fitsrhd(mfd,bfdefptr,&dsize,&mfdt,'O','Y',0,n);
   if (type < -990)			/* 1st look for TCTINI/SCFCRE errors */
      {
      if (type == -998)
         SCTMES(M_RED_COLOR,"problems creating image...");
      else
         SCTMES(M_RED_COLOR,"problems creating table...");
      reset_ERRO(fid);
      return (-9);
      }
   if (type < BFITS)				/* main header */
      {
      reset_ERRO(fid);
      return (-2);
      }


   /* extension 0 has to be treated specially */

   if (extno == 0)	
      {
      *info = 1;		/* always type IMAGE */
      extno = -1;		/* so it's recognized as an extension */
      goto after_exttypes; 
      }


   /* save type of header */

   if (dsize < 1)			/* empty primary header -> IMAGE */
      *info = 1;	
   else
      {
      *info = 0;
      if (type == ATABLE)
         *info = 3;
      else if (type == BTABLE)
         *info = 2;
      else if (type == IMAGE)
         *info = 1;
      }


   /* an extension cannot be the first header...
      so, we move on to next extension of FITS file */

  extens_loop:
   if (flag == 0) Mflag = -1;

   if (dsize > 0)
      {
      ln0 = fitssxd(dsize,1);		/* skip data matrix */
      extrecs += ln0;
      }

   if (*mfd > -1)
      {					/* clear previously created files */
      if (*info > 1)
         (void) TCTCLO(*mfd);
      else 
         (void) SCFCLO(*mfd);
      }

   *mfd = -1; mfdt = -1;
   hdr_init_M(bfdefptr,&adefptr,&pdefptr,1);	/* init again */

   type = fitsrhd(mfd,bfdefptr,&dsize,&mfdt,'O','Y',0,Mflag);
   if (type < -990)			/* 1st look for TCTINI/SCFCRE errors */
      {
      if (type == -998)
         SCTMES(M_RED_COLOR,"problems creating image...");
      else
         SCTMES(M_RED_COLOR,"problems creating table...");
      reset_ERRO(fid);
      return (-9);
      }
   if (type == EOFITS)
      {						/* we reached EOF */
      reset_ERRO(fid);
      return (-7);
      }

   extcount ++;				/* o.k. we passed one more extension */


   /* save type of extensions */

   *info = 0;			/* = 0 is bad... */
   if (type == ATABLE)
      *info = 3;
   else if (type == BTABLE)
      *info = 2;
   else if (type == IMAGE)
      *info = 1;
   else
      {
      if (dsize < 1) *info = 1;		/* empty headers -> IMAGE */
      }


   /* hunt down the required extension */

   if (extlabel[0] != '\0')	
      {
      CGN_UPSTR(bfdefptr->extname);
      if (strcmp(extlabel,bfdefptr->extname) == 0) 
         {
         if (*mfd > -1)
            {
            if (*info > 1)
               (void) TCTCLO(*mfd);
            else 
               (void) SCFCLO(*mfd);
            *mfd = -1;
            }
         *info = extcount;		/* save this extension no. */
         goto after_exttypes;
         }
      }
   
   if (extcount != extno) 		/* always true for extno = 1000 */
      goto extens_loop;

  /* here the main header + extensions (also ext. 0) join */

  after_exttypes:	
   ERRO_CONT = eco;        /* reset again */
   ERRO_LOG = elo;
   ERRO_DISP = edi;

   if (type == UKNOWN)
      {
      (void) snprintf(temp,(size_t) 400,
                  "Unknown FITS extension ( = %d)\n",extno);
      SCTPUT(temp);
       
      dclose(fid);
      return (-8);
      }


   /* if we just want to know the file type or 
      the extension no. of given EXTNAME, we can return now */

   if ((flag == 0) || (flag == -2))
      {
      TXDEF *tpntr;

      if (bfdefptr->extd != (char *) 0)
         {
         tpntr = (TXDEF *) bfdefptr->extd;
         free((char *)tpntr->col);
         free(bfdefptr->extd);
         }

      free((char *)bfdefptr);
      free((char *)adefptr);
      free((char *)pdefptr);
      dclose(fid);

      if (*mfd > -1)
         {
         fctpntr = FCT.ENTRIES + (*mfd);
         for (n=0; n<3; n++) fctpntr->FITSADDR[n] = (char *) 0;
         }

      return (0);
      }


   /* we really want the file - check, if we created the Midas frame */

   if (bfdefptr->cflag == 0)		/* extension header was bad... */
      {
      bfdefptr->cflag = 1;		/* force create_flag and try again */
      type = fitsrhd(mfd,bfdefptr,&dsize,&mfdt,'O','Y',0,Mflag);

      if (type < -990)			/* 1st look for TCTINI/SCFCRE errors */
         {
         if (type == -998)
            SCTMES(M_RED_COLOR,"problems creating image...");
         else
            SCTMES(M_RED_COLOR,"problems creating table...");
         dclose(fid);
         return (-9);
         }
      if (bfdefptr->cflag != -9)
         { 
         dclose(fid);
         return (-11);
         }
      }

   fctpntr = FCT.ENTRIES + (*mfd);

   fctpntr->KAUX[2] = 0;
   fctpntr->KAUX[3] = dsize;

   fctpntr->FITSEXT = extno;			/* save extension no. */
   bfdefptr->count += extrecs;			/* add skipped records */

   fctpntr->FITSADDR[0] = (char *) bfdefptr;
   fctpntr->FITSADDR[1] = (char *) adefptr;
   fctpntr->FITSADDR[2] = (char *) pdefptr;

   if (work[0] != '^')          /* return the path name */
      {
      work[kpath] = '\0';
      (void) strcpy(outbuf,work);
      }
   else
      {
      *outbuf = '^';
      *(outbuf+1) = '\0';
      }
   dclose(fid);
   }



/* if flag > 1 we have the FITS header already in memory */
/* ----------------------------------------------------- */

else
   {				/* file header already in  */
   Mflag = 1;
   imno = *mfd;
   fctpntr = FCT.ENTRIES + imno;
   bfdefptr = (BFDEF *) fctpntr->FITSADDR[0];

   if (flag == 2)
      {
      (void) fitsmove(bfdefptr);	/* only position file pointer ... */
      
      fctpntr->FITSOUT = 'X';		/* indicate that the data is in ... */
      dataout_ptr = outbuf;			/* now read the data */
      dataout_outtyp = fctpntr->DATTYP;
      dsize = fctpntr->KAUX[3];

      if (fctpntr->FILTYP == 1)				/* IMAGE */
         {
         if ((bfdefptr->bitpix == -16) || (bfdefptr->bitpix == 16))
            fitsrdmUI2(imno,bfdefptr,dsize,mfdt,'O',Mflag);
         else
            fitsrdm(imno,bfdefptr,dsize,mfdt,'O',Mflag);
         }
      else
         {
         if (fctpntr->FILTYP == 2)			/* BTABLE */
            fitsrbt(imno,bfdefptr,dsize,Mflag);
         else						/* ATABLE */
            fitsrat(imno,bfdefptr,dsize,Mflag);
         fctpntr->KAUX[2] = 0;			/* reset descr_changed_flag */
         }

      dclose(fid);
      }

   else
      {
      switch (bfdefptr->bitpix)		/* check original data format */
         {
         case   8 : n = D_I1_FORMAT; break;
         case -16 : n = D_UI2_FORMAT; break;
         case  16 : n = D_I2_FORMAT; break;
         case  32 : n = D_I4_FORMAT; break;
         case -32 : n = D_R4_FORMAT; break;
         case -64 : n = D_R8_FORMAT; break;
         }
      if (n != fctpntr->FORMAT)		/* data format changed => cannot copy */
         {
         dclose(fid);
         fid = -99;
         }
      else
         (void) fitsmove(bfdefptr);	/* only position file pointer ... */

      *info = fid;			/* return the file id of FITS file */
      }
   }

if (fctpntr->FILTYP > 1) n = TCSDSC(*mfd);		/* no IMAGE */

return (0);
}

/*

*/

#ifdef __STDC__
int fitsmove(BFDEF *bfdef)
#else
int fitsmove(bfdef)
BFDEF *bfdef;
#endif

{
char  *pc;

register int nr;


for (nr=0; nr<bfdef->count; nr++) dread(&pc,FITSLR);

return 0;
}

/*

*/

#ifdef __STDC__
int MyPut(int kdfmt, int kfelem, int kdn, char *inbuf)
#else
int MyPut(kdfmt,kfelem,kdn,inbuf)
int  kdfmt, kfelem, kdn;
char *inbuf;
#endif

/*
kdfmt = 8		D_I1_FORMAT
kdfmt = 16		D_I2_FORMAT
kdfmt = -16		D_UI2_FORMAT
kdfmt = 32		D_I4_FORMAT
kdfmt = -32		D_R4_FORMAT
kdfmt = -64		D_R8_FORMAT
*/

{
int  nbyte, intype, kk;

char   *opntr;



kk = kfelem - 1;		/* start in output buffer */
nbyte = get_byte(dataout_outtyp);	/* no. bytes of output data format */
opntr = dataout_ptr + (kk*nbyte);
if (kdfmt == 8)
   intype = D_I1_FORMAT;
else if (kdfmt == 16)
   intype = D_I2_FORMAT;
else if (kdfmt == -16)
   intype = D_UI2_FORMAT;
else if (kdfmt == 32)
   intype = D_I4_FORMAT;
else if (kdfmt == -32)
   intype = D_R4_FORMAT;
else 
   intype = D_R8_FORMAT;


/* do the conversion or just copy data */

conv_pix(opntr,inbuf,dataout_outtyp,intype,kdn);	

return 0;
}

