/*===========================================================================
  Copyright (C) 1995-2010 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
===========================================================================*/

/*+++++++++++++++++++++++ SC interface module SCFA +++++++++++++++++++++++
.LANGUAGE C
.IDENTIFICATION 
Module SCFA
.AUTHOR         
K. Banse 		ESO - Garching
.KEYWORDS       
standard interfaces, bulk data files
.ENVIRONMENT    
VMS and UNIX
.COMMENTS 
holds SCFSAV, SCFMOD, SCFREE, maxi
.REMARKS

.VERSION [1.00] 971015:	creation

 101221		last modif
----------------------------------------------------------------------------*/

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

#include <fileexts.h>
#include <osyparms.h>

#include   <fitsfmt.h>
#include   <fitsdef.h>

#define BIT_0  0x1

/*

*/

int SCFSAV(imno,flag)

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
save a Midas file as FITS file on disk
.ALGORITHM
use Prebens FITS I/O routines
.RETURNS
return status ( 0 = o.k)
-----------------------------------------------------------------------*/

int  imno;	/* IN: file no. */
int  flag;	/* IN: 0 = convert Midas image to FITS
		       1 = update internal FITS image/table
		       2 = convert Midas table to FITS */


{
char  ffmt, cut_opt;
char  origname[FCT_NAME_LEN];

int   fid, n, m, ftyp, datf, status;
int   n0, n1, e_c, e_d, e_l;
int   dscmod_only;
int   ddcopy();

void maxi();

struct FCT_STRUCT *fctpntr;




fctpntr = FCT.ENTRIES + imno;
dscmod_only = fctpntr->KAUX[2];		/* original descr. modified flag */

if (fctpntr->CATALOG[0] == 'T')
   {
   ftyp = F_TBL_TYPE;
   datf = D_R4_FORMAT;
   }
else
   {
   ftyp = F_IMA_TYPE;
   datf = fctpntr->FORMAT;		/* original data type */
   }

ffmt = 'O';			/* format flag : Basic FITS, Original */
cut_opt = 'N';

n1 = 1; n0 = 0;
SCECNT("GET",&e_c,&e_d,&e_l);
SCECNT("PUT",&n1,&n0,&n0);		/* disable SC errors */

if (fctpntr->O_NAMLEN == 0)
   (void) strcpy(origname,fctpntr->NAME);
else					/* internal FITS file */
   {
   (void) strcpy(origname,fctpntr->NAME+4);
   m = fctpntr->O_NAMLEN - 4;		/* we removed leading "FITZ" */
   origname[m] = '\0';
   }


/*  write out to FITS file `midFITS.mt'  */

fid = dopen("midFITS.mt",1,'S',6250);	/* open disk file for writing */	
if (fid < 0) return ERR_FILBAD;


dwinit(1);				/* init disk writing */

if (ftyp == F_IMA_TYPE) 
   {			
   if (flag == 0) 			/* Midas -> FITS */
      {
      int  unit, null, nv;
      float  lcut, hcut, cuts[2];

      (void) SCDRDR(imno,"LHCUTS",3,2,&nv,cuts,&unit,&null);
      lcut = cuts[0]; hcut = cuts[1];

      if ((nv!=2) || (hcut<=lcut)) 
         {				/* compute max/min cuts of data */
         maxi(imno,fctpntr->SIZE,cuts);
         (void) SCDWRR(imno,"LHCUTS",cuts,3,2,&unit);
         }
   
      status = fitswhd(imno,ftyp,datf,origname,ffmt,cut_opt,BFITS);
      if (status == 0)
         status = fitswdm(imno,datf,ffmt);	/* also update data */
      }

   else					/* internal FITS -> FITS */
      {
      status = fitswhd(imno,ftyp,datf,origname,ffmt,cut_opt,BFITS);
      if (status == 0)
         {
         fctpntr->FITSOUT = 'Y';		/* so SCFGET() will know... */
         if (dscmod_only == 1)			/* only update descr. */
            {		/* open original FITS file again + position it */
            int  gid;
            MID_fitsin(3,origname,-1,"","",&imno,&gid); 
            if (gid == -99)			/* data type changed... */
               {
               char  *datpntr;

               if (fctpntr->BDADDR[0] == (char *) 0)
                  status = SCFMAP(imno,F_I_MODE,1,-1,&m,&datpntr);
               else
                  status = ERR_NORMAL;
               if (status == ERR_NORMAL)
                  status = fitswdm(imno,datf,ffmt);   /* also write data */
               }
            else
               {
               status = ddcopy();		/* copy original FITS data */
               dclose(gid);
               }
            }
         else
            status = fitswdm(imno,datf,ffmt);	/* also update data */
         }
      }
   }

else 
   {				/* file is a table */
   status = 						/* primary header */
       fitswhd(imno,ftyp,datf,origname,ffmt,cut_opt,BFITSE); 
   if (status == 0)
      {							/* first extension */
      status = fitswhd(imno,ftyp,datf,origname,ffmt,cut_opt,ATABLE);
      if (status == 0)
         {
         if (ffmt == 'B') 
            status = fitswat(imno);		/* write ASCII table */
         else
            status = fitswbt(imno);		/* write Binary table */
         }
      }
   }

fctpntr->KAUX[2] = dscmod_only;		/* reset, if changed via fitswhd() */

SCECNT("PUT",&e_c,&e_d,&e_l);

n = dweof();				/* write EOF */
dclose(fid);

if ((n < 1) || (status != 0)) 
   {
   (void) osfdelete("midFITS.mt");
   return ERR_FILBAD;
   }
else
   return ERR_NORMAL;
}

/*

*/

void maxi(imno,datsize,cuts)
int  imno;
size_t  datsize;
float cuts[2];

{
int  nm, ioff, ns, data_bytes;
register int  nr;

char  *cpt;

float  *pix, lcut, hcut;

struct FCT_STRUCT *fctpntr;



fctpntr = FCT.ENTRIES + imno;
nm = fctpntr->DATTYP;
data_bytes = get_byte(nm);        /* no. of bytes needed */


ioff = 1;
lcut = hcut = 0.0;
nm = 100000;			/* at most chunks of 100 000 pixels */
if (nm > datsize) nm = (int) datsize;

cpt = (char *) malloc((size_t)(nm*data_bytes));
if (cpt == (char *) 0)
   {
   (void) printf("Out of memory in SCFSAV...\n");
   return;
   }

 
while (ioff <= (int) datsize)
   {
   (void) SCFGET(imno,ioff,nm,&ns,cpt);

   pix = (float *)cpt;
   if (ioff == 1) lcut = hcut = *pix;

   for (nr=0; nr<ns; nr++)
      {
      if (*pix<lcut)
         lcut = *pix;
      else if (hcut<*pix)
         hcut = *pix;
      pix++;
      }
   ioff += ns;
   }

cuts[0] = lcut;
cuts[1] = hcut;

free (cpt);
}

/*

*/

int SCFMOD(imno,dattype,size)

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
add the data blocks to a Midas file which was created with F_H_MODE
i.e. only the header part of the file: FCB + LDBs were created
.ALGORITHM
if size < 1 we just update the data type info
.RETURNS
return status ( 0 = o.k)
-----------------------------------------------------------------------*/

int  imno;	/* IN: file no. */
int  dattype;	/* IN: data type, D_R4_FORMAT, ... */
int  size;	/* IN: no. of data pixels */

{
int  status, data_bytes, lpex;
unsigned int  alq, nblock;

struct FCB_STRUCT  *fcbp;

struct FCT_STRUCT  *fctpntr;

size_t  *sptr;




if ( (imno < 0) || (imno >= FCT.MAXENT) )
   {
   status = ERR_INPINV;
   goto end_of_it;
   }
fctpntr = FCT.ENTRIES + imno;
fcbp = fctpntr->FZP;

data_bytes = get_byte(dattype);
fcbp->NOBYT = data_bytes;
fcbp->DFORMAT = dattype;
fcbp->PIXPBL = OUR_BLOCK_SIZE / data_bytes;

fctpntr->NOBYTE = fcbp->NOBYT;
fctpntr->FORMAT = fcbp->DFORMAT;
fctpntr->PIXPBL = fcbp->PIXPBL;
fctpntr->DATTYP = fctpntr->FORMAT;

fcbp->DATAINFO[4] = fcbp->DFORMAT;

if (size > 0)			/* allocate data blocks */
   {
   unsigned int  nobyt;

   fcbp->D1BLOCK = fcbp->LEXBDF + 1;	/* new start block of data */
   fcbp->DATAINFO[5] = (fcbp->D1BLOCK-1)*OUR_BLOCK_SIZE;
   fcbp->NDVAL = size;
   sptr = (size_t *) fcbp->XNDVAL;
   *sptr = (size_t) size;

   alq = (unsigned int) (OUR_BLOCK_SIZE - 1);
   nobyt = (unsigned int)data_bytes * (unsigned int)size;
   nobyt += alq;
   nblock = nobyt / OUR_BLOCK_SIZE;		/* no. of data blocks */

#if vms
   FSY_EXTBDF(fctpntr->FILEIDA,fctpntr->FILEIDB,fctpntr->DEVICE,
              (int)nblock,&lpex,&status);
   if ( (status & BIT_0) == 0 )
      {
      MID_ERROR("SCFMOD","SCFMOD/FSY_EXTBDF",status,0);
      return ERR_FRMNAC;
      }
#else

   nobyt = (unsigned int)fcbp->LEXBDF + nblock;
   nobyt *= OUR_BLOCK_SIZE;
   status = FSY_MODBDF(fctpntr->IOCHAN,nobyt,&lpex);
   if (status != ERR_NORMAL) goto end_of_it;
#endif

   /*
   printf("SCFMOD: lpex = %d, status = %x\n",lpex,status);
   */

   fcbp->PEXBDF = lpex;
   fcbp->DLBLOCK = lpex;

   fctpntr->STBLOK = fcbp->D1BLOCK;
   fctpntr->SIZE = (size_t) size;
   }

return ERR_NORMAL;
 

end_of_it:
MID_E2(1,imno,"...",status,1);
return status;
}

/*

*/

int SCFREE(type,nampat)

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
close opened frames
frames can be chosen via their iomode/type and/or names
.RETURNS
return	no. of files closed (>= 0)
-----------------------------------------------------------------------*/

char *type;		/* IN: type of opened frame,
			       = "X", "I" or "T" or "*"
			       for virtual memory, images, tables or all */
char *nampat;		/* IN: name pattern
			       "abc*" or "*" for all */

{
int  patlen, i, countr;

char  cb;
char  *ptr, origname[FCT_NAME_LEN];

struct FCT_STRUCT  *fctpntr;



cb = *type;
if ((cb >= 'a') && (cb <= 'z')) 
   cb +=  ('A' - 'a');
if ((cb != 'X') && (cb != 'T') && (cb != 'I'))
   cb = '*';				/* that's the default */

i = (int) strlen(nampat);
if ((i > 1) && (nampat[i-1] == '*'))
   patlen = i - 1;
else
   patlen = 0;
 
countr = 0;			/* no. of closed frames */


/*  loop through FCT and look for relevant entries */

fctpntr = FCT.ENTRIES;
for (i=0; i<FCT.MAXENT; i++)
   {
   if (fctpntr->NAME[0] != ' ')
      {
      if (fctpntr->FILTYP > 0)		/* for FITS files */
         {
	 if (fctpntr->O_NAMLEN == 0)
	     (void) strcpy(origname,fctpntr->NAME);
	 else					/* internal FITS file */
	     {
	     (void) strcpy(origname,fctpntr->NAME+4);
	     i = fctpntr->O_NAMLEN - 4;		/* we removed leading "FITZ" */
	     origname[i] = '\0';
	     }
         ptr = origname;
         }
      else
         ptr = fctpntr->NAME;

      if (patlen > 0)
         {
         if (strncmp(nampat,origname,(size_t)patlen) != 0)
            goto outer_loop;
         }
      
      if (cb != '*')
         {
         switch (cb)
            {
           case 'X':
            if (fctpntr->ACCESS == 'X')		/* virtual memory only */
               (void) SCFCLO(i);
            break;
           case 'I':
            if (fctpntr->CATALOG[0] != 'T')	/* images */
               (void) SCFCLO(i);
            break;
           default:				/* only 'T' possible */
            if (fctpntr->CATALOG[0] == 'T')
               (void) TCTCLO(i);
            }
         }
      else
         {
         if (fctpntr->CATALOG[0] == 'T')
            (void) TCTCLO(i);
         else
            (void) SCFCLO(i);
         }
      countr ++;
      }

outer_loop:
   fctpntr ++;
   }

return (countr);
}


