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

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENT        outtape.c
.LANGUAGE     C
.AUTHOR       P.Grosbol   ESO/IPG
.KEYWORDS     Encode data to FITS 
.PURPOSE      Convert disk files in internal MIDAS format to FITS 
              and write them to either tape or disk.
.COMMENT      Formats supported are : FITS 32 and tables
.VERSION      1.0  1988-Dec-01 : Creation,   PJG 
.VERSION      1.1  1989-Jan-25 : Modify input and add print,   PJG 
.VERSION      1.2  1989-May-03 : Open tape in READ_WRITE mode,  PJG
.VERSION      1.3  1989-Jun-12 : Change definition of unit+kunit,  PJG
.VERSION      1.4  1989-Oct-08 : Check both 'tape' and 'TAPE',  PJG
.VERSION      1.5  1990-Feb-19 : Search all catalog,  PJG
.VERSION      1.65 1990-Mar-30 : Check output file extension,  PJG
.VERSION      1.7  1990-Jul-04 : Filenames in catalog + U/L-case,  PJG
.VERSION      1.71 1990-Aug-31 : Force tables to ASCII,  PJG
.VERSION      1.75 1990-Sep-14 : Correct U/L-case + list no,  PJG
.VERSION      2.00 1991-Mar-07 : Change structures,  PJG
.VERSION      2.10 1991-Jul-02 : Check disk-file open status,  PJG
.VERSION      2.18 1991-Sep-26 : Correct catalog access,  PJG
.VERSION      2.20 1992-Mar-17 : Correct '.cat' + add physical dev.,  PJG
.VERSION      2.35 1992-Jun-17 : Add Rewind option + default no rewind,  PJG
.VERSION      2.40 1992-Jul-23 : Give position error + total size,  PJG
.VERSION      2.45 1992-Aug-31 : Skip deleted CAT-entries correctly,  PJG
.VERSION      2.46 1992-Dec-02 : Translating environment variables, CG
.VERSION      2.50 1993-Oct-29 : Update to new SC + prototypes, PJG
.VERSION      2.55 1993-Nov-12 : Replace SCKRDC with SCKGETC, PJG
.VERSION      2.65 1996-Jul-08 : Check for "" in input file name, PJG
.VERSION      2.70 1996-Jul-11 : Use SCETER for exit, test "" in output, PJG
.VERSION      2.80 1997-Jan-08 : Improve file-check for ASCII-catalogs, PJG
.VERSION      2.85 1997-Jan-22 : Change test of output file/dev, PJG

 090710		last modif
---------------------------------------------------------------------*/

#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 1
#endif

#include   <ctype.h>
#include   <stdlib.h>
#include   <stdio.h>
#include   <string.h>
#include   <osfile.h>
#include   <osparms.h>
#include   <fitsfmt.h>
#include   <fitsdef.h>
#include   <midas_def.h>

#define    MXCAT          101    /* Max. size of all catalogue names */
#define    NOFF          1000    /* File no. increment between cat's */

int main()
{
  char     file[129], name[129], tpname[129], line[81], fin[129];
  char     xname[32], devn[5], opt[4];
  char     cat[MXCAT], cname[129], fext[32];
  char     *pc, *pfile, *pe, *fout, *flist, *ext, *wext, *nfn;
  char     devt, ftype, ffmt, ctype;
  int      iparm[5], cinfo[11], unit[4];
  int      did, err, mfd, mft, mff, den, bf, catno, noff, fid;
  int      no, n, nval, list, null, ncat, nof, mr;
  float    tmbyte;
  struct filestatus status;

  SCSPRO("OUTTAPE");                            /* initiate MIDAS     */

  *cname = '\0'; wext = ".mt"; ext = "cat";
  catno = 5; noff = 0; ctype = '\0';
  nof = 0; mr = 0; fout = (char *) 0; mff = 0;
  did = -1;

  SCKGETC("P1",1,128,&nval,file);               /* read file list     */
  pc = pfile = file;
  list = 1; ftype = 'C';
  if (isalpha(*pc) || *pc=='"') {         /* is first char. a letter  */
     if (*pc=='"') {
	pfile++; pc++;
	while (*pc && *pc!='"') pc++;
	*pc++ = '\0';
      }
     else while (*pc && *pc!=',') pc++;

     if (!(*pc) || *pc==',') {           /* copy file name to 'cname' */
        if (*pc) *pc++ = '\0';
	strcpy(cname,pfile);
      }

     if ((pe=strrchr(cname,'.'))) {      /* check if with extension   */
        *pe++ = '\0'; ext = pe;
        ftype = '\0'; list = 0;
        if (!strcmp(ext,"cat")) { 
	  ftype = 'C'; list = 1;
	}
      }
     if (ftype=='C') {
	SCCSHO(cname,&n,&ncat);
	strcpy(line,cname); strcat(line,".cat");
	fid = osaopen(line,READ);          /* find catalog type      */
	osaread(fid, line, 5);
	osaclose(fid);
	ctype = line[2];
      }
   }
  else {
    catno = 0;
    SCKRDI("CATALINF",1,11,&nval,cinfo,unit,&null);
    SCKRDC("CATALOGS",1,1,MXCAT,&nval,cat,unit,&null);
    nval = 0;
    for (n=5; n<10; n++) nval = (nval || 0<cinfo[n]);
    if (!nval) 
      SCETER(1,"Error: Active catalog must be SET if input starts with digit");
  }

  flist =  (*pc) ? pc : "*";                 /* default to all 1-9999 */
  if (deflist(flist))                        /* initiate file list    */
    SCETER(2,"Error: bad number list of catalog entries");

  pc = ext; n = 0;                           /* copy full extension   */
  fext[n++] = '.';
  while ((fext[n++] = *pc++));

  SCKRDI("INPUTI",1,2,&nval,iparm,unit,&null);  /* density and block  */
  den = (nval<1) ? 6250 : iparm[0];
  bf =  (nval<2) ? 10 : iparm[1];
  if (bf<1) bf = 1; else if (10<bf) bf = 10;

  SCKGETC("P2",1,128,&nval,name);               /* read device/file   */
  if (*name=='"') {
     pc = pe = name;
     while (*pc) if (*pc=='"') pc++; else *pe++ = *pc++;
     *pe = '\0';
   }
  for (n=0; n<4; n++) 
     devn[n] = (('A'<=name[n]) && (name[n]<='Z')) ? name[n]+'a'-'A' : name[n];
  devn[n] = '\0';

  if (strncmp(devn,"tape",4)) {
     CGN_LOGNAM(name,tpname,128);
     strcpy(name,tpname);                         /* copy actual name     */
     if (osfinfo(name,&status) == 0)              /* if name exists       */
       devt = (S_ISCHR(status.protection)) ? 'B' : 'S';   /* block:stream */
     else                                         /* check if remote tape */
       devt = (((pc=strchr(name,':')) || (pc=strchr(name,'!'))) &&
               (*(pc+1)=='/')) ? 'B' : 'S';
   }
  else {
        pc = name;
        while (*pc) { if (('A'<=*pc) && (*pc<='Z')) *pc += 'a'-'A'; pc++; }
        if (osfphname(name,tpname)) {  /* get physical name of device */
           pc = name;
           while (*pc) { if (('a'<=*pc) && (*pc<='z')) *pc += 'A'-'a'; pc++; }
           if (osfphname(name,tpname))
	     SCETER(3,"Error: device not defined");
	 }
        devt = 'B';                             /* block type device  */
	strcpy(name,tpname);                    /* copy physical name */
      }	
  
  if (devt == 'B') {
    did = dopen(name,READ_WRITE,devt,den);
    if (did < 0) {    /* open block device  */
       SCTPUT(osmsg());
       SCETER(4,"Error: cannot open tape-device");
     }	
  }
  else {                                        /* else stream device */
     pc = name;
     while(*pc && *pc!='.') pc++;
     if (*pc=='.') {
        *pc++ = '\0'; n = 0; xname[n++] = '.';
        while(*pc && *pc!='.') xname[n++] = *pc++;
        xname[n] = '\0'; if (1<n) wext = xname;
      }
   }

  opt[0] = 'N';              /* append flag : No append,Append,Rewind */
  opt[1] = 'S';              /* print  flag : No, Short, Full         */
  opt[2] = 'N';              /* cut    flag : No cuts, Cuts used      */
  SCKGETC("P3",1,3,&nval,opt);               /* read options          */

  ffmt = 'O';		/* format flag is fixed to: Original    */

  if (devt=='B') {                           /* position tape         */
     err = 0;
     if (opt[0]=='A') err = dapos(-1);
       else if (opt[0]=='R') err = dapos(0);
     if (err)
	SCETER(5,"Error: cannot position tape device");
   }
  no = 1; nval = 0;
  SCECNT("PUT",&no,&nval,&nval);             /* disable SC errors     */

  do {                                        /* go through all files */
    if (ftype=='C') {                         /* files from catalog   */
      if (!cname[0]) {
	while (catno<5 && (cinfo[catno]<=0 || cinfo[catno+5]<=0)) catno++;
	if (5<=catno) break;                /* no more cat's - finish */
	no = 0;
	for (n=cinfo[catno++]-1; cat[n]!=' ' && no<cinfo[10];)
	  cname[no++] = cat[n++];
	cname[no] = '\0';
	deflist(flist);
	SCCSHO(cname,&n,&ncat);             /* get last entry in cat. */
	fid = osaopen(cname,READ);          /* find catalog type      */
	osaread(fid, line, 5);
	osaclose(fid);
	ctype = line[2];
	sprintf(line,"Start catalogue(%c) : >%s< with %d entries"
		,ctype,cname,n);
	SCTPUT(line);
      }

      if (!getlist(&no) || ncat<no) {       /* get new file no.       */
	*cname = '\0';
	noff += NOFF * (ncat/NOFF + 1);
	continue;
      }
      
      if (no<1) continue;                /* zero and negative entries */

      if (SCCFND(cname,no,fin)) {
	sprintf(line,"Warning: Cannot open catalog file: %s, %d",cname,no);
	SCTPUT(line);
	continue;
      }
      if (*fin==' ') continue;                /* file does not exist  */
    }
    else {                                    /* explicit files       */
      if (list) {
	if (!getlist(&no)) break;             /* no more files - exit */
        outname(cname,no,'o');		/* 'o' like 'original version' */
	nfn = newfn('I',fext);
      }
      else { nfn = cname; pc = ext; *(--pc) = '.'; }
      strcpy(fin,nfn);
    }

    mft = -1;
    err = SCFINF(fin,1,iparm);                /* get type of MIDAS file */
    if (err == ERR_NORMAL) {
      mft = iparm[1];
      mff = D_R4_FORMAT;
      err = SCFINF(fin,4,iparm);              /* check if FITS format   */
      if (iparm[2]!=0) {
	sprintf(line,"Warning: >%s< skipped as already in FITS format",fin);
	SCTPUT(line); continue;
      }
    }
    else if (ctype=='A') {
      fid = osaopen(fin,READ);                     /* open text file    */
      n = osaread(fid,line,80);
      osaclose(fid);
      if (!strncmp(line,"SIMPLE  =",9)) {
	sprintf(line,"Warning: >%s< skipped as already in FITS format",fin);
	SCTPUT(line); continue;
      }
      mft = F_ASC_TYPE;
    }
    else {
      sprintf(line,"Warning: Cannot open or find type of file >%s<",fin);
      SCTPUT(line); continue;
    }

    if (mft==F_IMA_TYPE) {                  /* if image get data format */
      SCFINF(fin,2,iparm);
      mff = iparm[1];
    }

    if (devt=='S') {                         /* output file open it    */
      if (list) {
	outname(name,no+noff,'o');
	fout = newfn('I',wext);
      }
      else {
	fout = name; pc = name;
	while (*pc || *pc=='.') pc++;
	strcpy(pc,wext);
      }
      did = dopen(fout,WRITE,devt,den);
      if (did < 0) {    /* open disk file         */
	SCTPUT(osmsg());
	SCETER(6,"Error: cannot open disk-file");
      }
      bf = 1;
    }
    dwinit(bf);

    err = 0;
    switch (mft) {                              /* check which format        */
       case F_IMA_TYPE :                        /* file is an image          */
            SCFOPN(fin,mff,0,mft,&mfd);         /* open image file           */
            err = fitswhd(mfd,mft,mff,fin,ffmt,opt[2],BFITS);	/* prime hdr */
	    if (err) break;
            err = fitswdm(mfd,mff,ffmt);        /* write prime data          */
            SCFCLO(mfd);                        /* close image file          */
            break;
       case F_TBL_TYPE :                        /* file is a table           */
            TCTOPN(fin,F_I_MODE,&mfd);          /* open table file           */
            err = fitswhd(mfd,mft,mff,fin,ffmt,opt[2],BFITSE);	/* prime hdr */
	    if (err) break;
            err = fitswhd(mfd,mft,mff,fin,ffmt,opt[2],ATABLE); /* extension  */
	    if (err) break;
            else err = fitswbt(mfd);            /* write Binary table        */
            TCTCLO(mfd);                        /* close table file          */
            break;
       case F_FIT_TYPE :                       /* file is a fit-format       */
            SCFOPN(fin,mff,0,mft,&mfd);        /* open fit file              */
            err = fitswhd(mfd,mft,mff,fin,ffmt,opt[2],BFITSE); 
            SCFCLO(mfd);                       /* close fit file             */
            break;
       case F_ASC_TYPE :                       /* file is ASCII char.        */
	    text_open(fin,READ);
            err = fitswhd(mfd,mft,mff,fin,ffmt,opt[2],BFITSE); /* prime hdr. */
	    text_close();
            break;
       default   : sprintf(line,"Warning: file %-16s unknown type>%d<",
			   fin,mft);
                   SCTPUT(line);
	           continue;
	  }
    if (err) 
       {
       sprintf(line,"Warning: file %-16s NOT completed - device error",fin);
       SCTPUT(line); break;
       }
    if ((n=dweof())<=0) 
       {
       sprintf(line,"Warning: file %-16s NOT written",fin);
       SCTPUT(line); continue;
       }

    if (devt=='S') 
       {
       dclose(did);
       sprintf(line,"File %-16s written to disk> %s",fin,fout);
       }
    else
       sprintf(line,"File %-16s written to tape with %5d records",fin,n);
    SCTPUT(line);

    nof++; mr += n;
  } while (list);

  tmbyte = (2880.0/1048576.0) * mr;
  if (tmbyte<0.01) tmbyte = 0.01;
  sprintf(line,"Total %d files written with %8.2f Mbytes",nof,tmbyte);
  SCTPUT(line);
  if (devt!='S') dclose(did);
  SCSEPI();
  exit(0);
}
