/*===========================================================================
  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;

}
 */
