/*===========================================================================
  Copyright (C) 2001 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 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding 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
===========================================================================*/
/* Program  : readslitflats.c                                              */
/* Author   : G. Mulas  -  ITAL_FLAMES Consortium                          */
/* Date     :                                                              */
/*                                                                         */
/* Purpose  : Read input slit FF catalogue to prepare slitff structure     */
/*                                                                         */
/*                                                                         */
/* Input:     input catalogue with:                                       */
/*            slitff_common                                                */
/*            slitff_norm                                                  */
/*            slitff_nsigma                                                */
/*            slitff_bound                                                 */
/*            slitff_data                                                  */
/*            slitff_sigma                                                 */
/*            slitff_badpixels                                             */
/*            MIDAS format frames                                          */
/*                                                                         */
/*                                                                         */
/*                                                                         */
/*                                                                      */
/* Output:    none (a slitff structure is set-up)                       */
/*                                                                         */
/* DRS Functions called:                                                   */
/*              l3tensor                                                   */ 
/*              free_l3tensor                                              */ 
/*                                                                         */
/* Pseudocode:                                                             */
/*             open input cat, count slitFF, common 3D frames,             */
/*             check input is proper , get basic descriptors by common frm */
/*             read common frm, read normalizzation frm, read all slit FF  */
/*             copy all relevant data in the data structure members        */
/*                                                                         */ 
/* Version  :                                                              */
/* Last modification date: 2002/08/05                                      */
/* Who     When        Why                Where                            */
/* AMo     02-08-05   Add header         header                            */
/*-------------------------------------------------------------------------*/


#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <flames_midas_def.h>
#include <flames_uves.h>
#include <flames_dfs.h>
#include <flames_checksize.h>
#include <flames_checksize2.h>
#include <flames_newmatrix.h>
#include <uves_msg.h>
#include <flames_readslitflats.h>
#include <flames_allocslitflats.h>


//static int check_bound(int32_t* lb,int32_t* hb);

flames_err 
readslitflats(const cpl_frameset *catname, allslitflats *slitflats)
{
  int entrynum=0;
  int status=0;
  int actvals=0;
  int actsize=0;
  int unit=0;
  int null=0;
  int ibuf=0;
  int commonid=0;
  int normid=0;
  int frameid=0;
  int sigmaid=0;
  int badid=0;
  int boundid=0;
  int32_t ncommon=0;
  int32_t nnorm=0;
  int32_t iframe=0;
  int32_t ***longarray=0;
  char filename[CATREC_LEN+1];
  char identifier[CATREC_LEN+1];
  char commoname[CATREC_LEN+1];
  char normname[CATREC_LEN+1];
  char* fixed_name=NULL;
  slitFF *myslit=0;
  frame_mask *fmvecbuf1=0;
  int32_t *lvecbuf1=0;
  int32_t *lvecbuf2=0;
  int32_t *lvecbuf3=0;
  int32_t *lvecbuf4=0;
  int32_t *lvecbuf5=0;
  int32_t maxiorderixindex=0;
  int32_t iorderixindex=0;
  float halfwidth=0;

  memset(filename, '\0', CATREC_LEN+1);
  memset(identifier, '\0', CATREC_LEN+1);
  memset(commoname, '\0', CATREC_LEN+1);
  memset(normname, '\0', CATREC_LEN+1);

  slitflats->nflats = 0;
  ncommon = 0;
  /* first open the catalog, count the int32_t slit frames and the common
     3D frame present */
  entrynum = 0;

  do {

     if ((status = SCCGET(catname, 1, filename, identifier, &entrynum)) != 0) {
      /* error getting catalog entry */
      return flames_midas_error(MAREMMA);
     }
    uves_msg_debug("reading file >%s< with identifier >%s< id=%d",
         filename,identifier,entrynum);
     /* did I get a valid catalog entry? */
    if (filename[0] != ' ') {
      /* is this a int32_t slit FF frame? */
      uves_msg_debug("identifier=>%s<",identifier);
      if (strncmp(identifier, "Normalised slit FF",18) == 0) {
	//if (strncmp(identifier, "SLIT_FF_DT",10) == 0) {
    slitflats->nflats++;
    uves_msg_debug("reading file >%s< with identifier >%s< id=%d",
         filename,identifier,entrynum);
      }
      /* is this a common frame? */
      if (strncmp(identifier, "Common data for slit FF",23) == 0) {
	//if (strncmp(identifier, "SLIT_FF_COM",11) == 0) {
    ncommon++;
    strcpy(commoname, filename);
      }
      /* is this a normalisation frame? */
      if (strncmp(identifier, "Normalisation data for slit FF",30) == 0) {
	//if (strncmp(identifier, "SLIT_FF_NOR",11) == 0) {
    nnorm++;
    strcpy(normname, filename);
      }
    }

  } while (filename[0] != ' ');


  /* did I get at least 1 int32_t slit frame name? */
  if (slitflats->nflats < 1) {
    /* I need at least 1 int32_t slit FF frame! */
    return flames_midas_error(MAREMMA);
  }

  /* did I get exactly 1 common frame name? */
  if (ncommon != 1) {
    /* I need exactly 1 common frame name! */
    return flames_midas_error(MAREMMA);
  }


  /* did I get exactly 1 normalisation frame name? */
  if (nnorm != 1) {
    /* I need exactly 1 normalisation frame name! */
    return flames_midas_error(MAREMMA);
  }



  /* open the common frame to get the descriptors */
  if ((status = SCFOPN(commoname, D_I4_FORMAT, 0, F_IMA_TYPE, 
               &commonid)) != 0) {
    /* could not open the frame */
    return flames_midas_error(MAREMMA);
  }


  /* read the relevant information from the frame */
  if ((status = SCDRDI(commonid, "NFLATS", 1, 1, &actvals, &ibuf, 
               &unit, &null)) != 0) {
    /* problems reading NFLATS: complain... */
    return flames_midas_error(MAREMMA);
  }

  if (slitflats->nflats != (int32_t) ibuf) {
    /* how come I have fewer files in the catalog than are recorded in
       the common data frame? Bail out*/
    return flames_midas_error(MAREMMA);
  }




  if ((status = SCDRDI(commonid, "ROWS", 1, 1, &actvals, &ibuf, 
               &unit, &null)) != 0) {
    /* problems reading ROWS: complain... */
    return flames_midas_error(MAREMMA);
  }
  slitflats->subrows = (int32_t) ibuf;
  if ((status = SCDRDI(commonid, "COLS", 1, 1, &actvals, &ibuf, 
               &unit, &null)) != 0) {
    /* problems reading COLS: complain... */
    return flames_midas_error(MAREMMA);
  }

  slitflats->subcols = (int32_t) ibuf;
  if ((status = SCDRDD(commonid, "STARTX", 1, 1, &actvals, 
               &slitflats->substartx, &unit, &null)) != 0) {
    /* problems reading STEPX: complain... */
    return flames_midas_error(MAREMMA);
  }
  if ((status = SCDRDD(commonid, "STARTY", 1, 1, &actvals, 
               &slitflats->substarty, &unit, &null)) != 0) {
    /* problems reading STEPY: complain... */
    return flames_midas_error(MAREMMA);
  }
  if ((status = SCDRDD(commonid, "STEPX", 1, 1, &actvals, 
               &slitflats->substepx, &unit, &null)) != 0) {
    /* problems reading STEPX: complain... */
    return flames_midas_error(MAREMMA);
  }

  if ((status = SCDRDD(commonid, "STEPY", 1, 1, &actvals, 
               &slitflats->substepy, &unit, &null)) != 0) {
    /* problems reading STEPY: complain... */
    return flames_midas_error(MAREMMA);
  }
  if ((status = SCDRDC(commonid, "CHIPCHOICE", 1, 1, 1, &actvals, 
               &slitflats->chipchoice, &unit, &null)) != 0) {
    /* problems reading CHIPCHOICE: complain... */
    return flames_midas_error(MAREMMA);
  }
  if ((status = SCDRDD(commonid, "RON", 1, 1, &actvals, 
               &slitflats->ron, &unit, &null)) != 0) {
    /* problems reading RON: complain... */
    return flames_midas_error(MAREMMA);
  }

  if ((status = SCDRDD(commonid, "GAIN", 1, 1, &actvals, 
               &slitflats->gain, &unit, &null)) != 0) {
    /* problems reading GAIN: complain... */
    return flames_midas_error(MAREMMA);
  }
  if ((status = SCDRDI(commonid, "ORDERLIM", 1, 1, &actvals, 
               &slitflats->firstorder, &unit, &null)) != 0) {
    /* problems reading FIRSTORDER: complain... */
    return flames_midas_error(MAREMMA);
  }
  if ((status = SCDRDI(commonid, "ORDERLIM", 2, 1, &actvals, 
               &slitflats->lastorder, &unit, &null)) != 0) {
    /* problems reading LASTORDER: complain... */
    return flames_midas_error(MAREMMA);
  }
  if ((status = SCDRDI(commonid, "TAB_IN_OUT_OSHIFT", 1, 1, &actvals, 
               &slitflats->tab_io_oshift, &unit, &null)) != 0) {
    /* problems reading LASTORDER: complain... */
    return flames_midas_error(MAREMMA);
  }

  uves_msg_debug("nflats=%d",slitflats->nflats);
  uves_msg_debug("nrows=%d",slitflats->subrows);
  uves_msg_debug("ncols=%d",slitflats->subcols);
  uves_msg_debug("startx=%f",slitflats->substartx);
  uves_msg_debug("starty=%f",slitflats->substarty);
  uves_msg_debug("stepx=%f",slitflats->substepx);
  uves_msg_debug("stepy=%f",slitflats->substepy);
  uves_msg_debug("chipchoice=%c",slitflats->chipchoice);
  uves_msg_debug("ron=%f",slitflats->ron);
  uves_msg_debug("gain=%f",slitflats->gain);
  uves_msg_debug("firstorder=%d",slitflats->firstorder);
  uves_msg_debug("lastorder=%d",slitflats->lastorder);
  uves_msg_debug("tabinoushift=%d",slitflats->tab_io_oshift);


  /* allocate the 3D temporary buffer for the common frame */
  longarray = l3tensor(0, 2, 0, 
               (slitflats->lastorder-slitflats->firstorder), 
               0, slitflats->subcols-1);


    uves_msg_debug("actsize=%d,check=%d lastord=%d,firstord=%d,subcols=%d",
		     actsize,3*(slitflats->lastorder-slitflats->firstorder+1)*slitflats->subcols,slitflats->lastorder,slitflats->firstorder,slitflats->subcols);
  /* read the common frame */
  if ((status = SCFGET(commonid, 1, 
               3*(slitflats->lastorder-
              slitflats->firstorder+1)*slitflats->subcols, 
               &actsize, (char *)(&longarray[0][0][0]))) != 0) {
    /* problems reading common frame: complain */

    return flames_midas_error(MAREMMA);
  }
  else if (actsize != 3*(slitflats->lastorder-
             slitflats->firstorder+1)*slitflats->subcols) {
    /* I read fewer elements than expected: complain... */

    return flames_midas_error(MAREMMA);
  }


  /* close the common frame */
  if ((status = SCFCLO(commonid)) != 0) {
    /* problems closing common frame */
    return flames_midas_error(MAREMMA);
  }

  /* allocate the arrays in the structure */
  if ((status = allocslitflats(slitflats)) != NOERR) {
    /* problem allocating internal arrays of slitflats */
    return flames_midas_error(MAREMMA);
  }
  /* put values in the structure */
  lvecbuf1 = longarray[0][0];      //lower bounds
  lvecbuf2 = longarray[1][0];      //upper bounds
  lvecbuf3 = longarray[2][0];      //bad pixels 
  lvecbuf4 = slitflats->lowbound[0];
  lvecbuf5 = slitflats->highbound[0];
  memcpy(lvecbuf4, lvecbuf1, (slitflats->lastorder-slitflats->firstorder+1)*
     slitflats->subcols*sizeof(int32_t));
  memcpy(lvecbuf5, lvecbuf2, (slitflats->lastorder-slitflats->firstorder+1)*
     slitflats->subcols*sizeof(int32_t));
  fmvecbuf1 = slitflats->goodx[0];
  maxiorderixindex = ((slitflats->lastorder-slitflats->firstorder+1)*
              slitflats->subcols)-1;
  for (iorderixindex=0; iorderixindex<=maxiorderixindex; iorderixindex++) {
    fmvecbuf1[iorderixindex] = (frame_mask)lvecbuf3[iorderixindex];
  }



  /* free the temporary buffer */
  free_l3tensor(longarray, 0, 2, 0, 
        (slitflats->lastorder-slitflats->firstorder),
        0, slitflats->subcols-1);


  /* open the normalisation frame */
  if ((status = SCFOPN(normname, FLAMESDATATYPE, 0, F_IMA_TYPE, 
               &normid)) != 0) {
    /* could not open the frame */
    return flames_midas_error(MAREMMA);
  }


  /* read the normalisation frame */
  if ((status = SCFGET(normid, 1, 
               (slitflats->lastorder-slitflats->firstorder+1)
               *slitflats->subcols, 
               &actsize, (char *)(&slitflats->normfactor[0][0]))) 
      != 0) {
    /* problems reading normalisation frame: complain */
    return flames_midas_error(MAREMMA);
  }
  else if (actsize != (slitflats->lastorder-slitflats->firstorder+1)*
       slitflats->subcols) {
    /* I read fewer elements than expected: complain... */
    return flames_midas_error(MAREMMA);
  }
  /* close the normalisation frame */
  if ((status = SCFCLO(normid)) != 0) {
    /* problems closing common frame */
    return flames_midas_error(MAREMMA);
  }

  /* rescan the catalog from the beginning and, this time, read all
     int32_t slit FF frame names */
  /* allocate the temporary 3D buffer for boundaries */
  longarray = l3tensor(0, 1, 0, slitflats->lastorder-slitflats->firstorder, 
               0, slitflats->subcols-1);
  lvecbuf1 = longarray[0][0];
  lvecbuf2 = longarray[1][0];
  maxiorderixindex = ((slitflats->lastorder-slitflats->firstorder+1)*
              slitflats->subcols)-1;
  iframe = 0;
  entrynum = 0;



  do {
    if ((status = SCCGET(catname, 1, filename, identifier, &entrynum)) != 0) {
      /* error getting catalog entry */
      return flames_midas_error(MAREMMA);
    }
    uves_msg_debug("reading file >%s< with identifier %s id=%d",
         filename,identifier,entrynum);

    myslit = slitflats->slit+iframe;
    /* did I get a valid catalog entry? */
    if (filename[0] != ' ') {
      uves_msg_debug("identifier=>%s<",identifier);

      /* is this a int32_t slit FF frame? */
      if (strncmp(identifier, "Normalised slit FF",18) == 0) {
	//if (strncmp(identifier, "SLIT_FF_DT",10) == 0) {
    /* open the frame */

    if ((status = SCFOPN(filename, FLAMESDATATYPE, 0, F_IMA_TYPE, 
                 &frameid)) != 0) {
      /* could not open the frame */
      return flames_midas_error(MAREMMA);
    }

    strcpy(myslit->framename, filename);
    uves_msg_debug("dataname=%s",filename);

    /* do some consistency checks */
    if (checksize(frameid, slitflats) != NOERR) {
      /* the file dimensions do not match */
      return flames_midas_error(MAREMMA);
    }
 
    /* read the frame */
    if ((status = SCFGET(frameid, 1, 
                 slitflats->subcols*slitflats->subrows, 
                 &actsize, 
                 (char *) &myslit->data[0][0]))
        != 0) {
      /* error reading frame data */
      return flames_midas_error(MAREMMA);
    }
 

    if (actsize != slitflats->subcols*slitflats->subrows) {
      /* wrong number of elements read */
      return flames_midas_error(MAREMMA);
    }

 
    /* read the y shift of this frame */
    if ((status = SCDRDD(frameid, "YSHIFT", 1, 1, &actvals, 
                 &myslit->yshift, &unit, &null)) 
        != 0) {
      /* problems reading sigma file name from descriptor */
    }
 
    /* read the order halfwidth of this frame */
    if ((status = SCDRDR(frameid, "HALFWIDTH", 1, 1, &actvals, 
                 &halfwidth, &unit, &null)) != 0) {
      /* problems reading sigma file name from descriptor */
    }
    myslit->halfwidth=halfwidth;
 

    /* read the name of the sigma frame */
    if ((status = SCDGETC(frameid, "SIGMAFILE", 1, CATREC_LEN, &actvals, 
                  filename)) != 0) {
      /* problems reading sigma file name from descriptor */
    }


        //AMo: we fix possible .bdf estention
        fixed_name=flames_fix_estention(filename);
        strcpy(filename,fixed_name);
        cpl_free(fixed_name);

 
    /* open the sigma frame */
    if ((status = SCFOPN(filename, FLAMESDATATYPE, 0, F_IMA_TYPE, 
                 &sigmaid)) != 0) {
      /* could not open the frame */
      return flames_midas_error(MAREMMA);
    }


    strcpy(myslit->sigmaname, filename);
    uves_msg_debug("sigmaname=%s",filename);
    /* do some consistency checks */
    if (checksize(sigmaid, slitflats) != NOERR) {
      /* the file dimensions do not match */
      return flames_midas_error(MAREMMA);
    }
 
    /* read the frame */
    if ((status = SCFGET(sigmaid, 1, 
                 slitflats->subcols*slitflats->subrows, 
                 &actsize, 
                 (char *) &myslit->sigma[0][0]))
        != 0) {
      /* error reading frame sigma */
      return flames_midas_error(MAREMMA);
    }
 

    if (actsize != slitflats->subcols*slitflats->subrows) {
      /* wrong number of elements read */
      return flames_midas_error(MAREMMA);
    }

    /* close the sigma frame */
    if ((status = SCFCLO(sigmaid)) != 0) {
      /* problems closing sigma frame */
      return flames_midas_error(MAREMMA);
    }

 
    /* read the name of the badpixel frame */
    if ((status = SCDGETC(frameid, "BADPIXELFILE", 1, CATREC_LEN, 
                  &actvals, filename)) != 0) {
      /* problems reading badpixel file name from descriptor */
    }

        //AMo: we fix possible .bdf estention
        fixed_name=flames_fix_estention(filename);
        strcpy(filename,fixed_name);
    cpl_free(fixed_name);
 

    /* open the sigma frame */
    if ((status = SCFOPN(filename, FLAMESMASKTYPE, 0, F_IMA_TYPE, 
                 &badid)) != 0) {
      /* could not open the frame */
      return flames_midas_error(MAREMMA);
    }


    strcpy(myslit->badname, filename);
    uves_msg_debug("badname=%s",filename);
    /* do some consistency checks */
    if (checksize(badid, slitflats) != NOERR) {
      /* the file dimensions do not match */
      return flames_midas_error(MAREMMA);
    }
 
    /* read the frame */
    if ((status = SCFGET(badid, 1, 
                 slitflats->subcols*slitflats->subrows, 
                 &actsize, 
                 (char *) &myslit->badpixel[0][0]))
        != 0) {
      /* error reading frame badpixel */
      return flames_midas_error(MAREMMA);
    }

 
    if (actsize != slitflats->subcols*slitflats->subrows) {
      /* wrong number of elements read */
      return flames_midas_error(MAREMMA);
    }

    /* close the badpixel frame */
    if ((status = SCFCLO(badid)) != 0) {
      /* problems closing badpixel frame */
      return flames_midas_error(MAREMMA);
    }

    /* read the name of the boundaries frame */
    if ((status = SCDGETC(frameid, "BOUNDARYFILE", 1, CATREC_LEN, 
                  &actvals, filename)) != 0) {
      /* problems reading boundaries file name from descriptor */
    }

        //AMo: we fix possible .bdf estention
        fixed_name=flames_fix_estention(filename);
        strcpy(filename,fixed_name);
    cpl_free(fixed_name);

 

    /* open the boundary frame */
    if ((status = SCFOPN(filename, D_I4_FORMAT, 0, F_IMA_TYPE, 
                 &boundid)) != 0) {
      /* could not open the frame */
      return flames_midas_error(MAREMMA);
    }

    strcpy(myslit->boundname, filename);
    uves_msg_debug("boundname=%s",filename);
 
    /* do some consistency checks */
    if (checksize2(boundid, slitflats) != NOERR) {
      /* the file dimensions do not match */
      return flames_midas_error(MAREMMA);
    }
 
 
    /* read the frame */
    if ((status = 
         SCFGET(boundid, 1, 
            2*(slitflats->lastorder-slitflats->firstorder+
               1)*slitflats->subcols, &actsize, 
            (char *) &longarray[0][0][0])) != 0) {
      /* error reading boundaries frame */
      return flames_midas_error(MAREMMA);
    }

    if (actsize != 2*(slitflats->lastorder-slitflats->firstorder+
              1)*slitflats->subcols) {
      /* wrong number of elements read */
      return flames_midas_error(MAREMMA);
    }


    /* copy the data to the appropriate structure members */
    lvecbuf4 = myslit->lowbound[0];
    lvecbuf5 = myslit->highbound[0];
    memcpy(lvecbuf4, lvecbuf1, (slitflats->lastorder-slitflats->firstorder+
                    1)*slitflats->subcols*sizeof(int32_t));
    memcpy(lvecbuf5, lvecbuf2, (slitflats->lastorder-slitflats->firstorder+
                    1)*slitflats->subcols*sizeof(int32_t));


 
    /* I suppose I ought to read in also yshift and halfwidth here, 
       I will code it in as soon as ESO provides the appropriate
       recipe (amodigli?)*/
    /* close the boundaries frame */
 
    if ((status = SCFCLO(boundid)) != 0) {
      /* problems closing boundaries frame */
      return flames_midas_error(MAREMMA);
    }
 
    /* close the data frame */
    if ((status = SCFCLO(frameid)) != 0) {
      /* problems closing data frame */
      return flames_midas_error(MAREMMA);
    }
    iframe++;
    myslit = slitflats->slit+iframe;

 
      }
    }
  } while (filename[0] != ' ');

 
  /* I read it all, free buffers */
  free_l3tensor(longarray, 0, 1, 0, 
        slitflats->lastorder-slitflats->firstorder, 
        0, slitflats->subcols-1);




  return(NOERR);

}


/*
static int check_bound(int32_t* lb,int32_t* hb)
{


  //Added check on bounds
  int32_t index=0;
  int32_t iframe=0;

  int j=0;
  for (iframe=2; iframe<=2 ;iframe++) {
    for(j=0;j<4;j++) {
      for(index=j*4096+20; index<j*4096+30 ;index++) {
	uves_msg_warning("x=%d y=%d index=%d lowbound=%d highbound=%d\n",
			 index-j*4096,j,index,lb[index],hb[index]);
      }
    }
  }
 
  return 0;

}
*/
