/*===========================================================================
  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  : mainslitdivide.c                                             */
/* Author   : G. Mulas  -  ITAL_FLAMES Consortium                          */
/* Date     :                                                              */
/*                                                                         */
/* Purpose  : Missing                                                      */
/*                                                                         */
/*                                                                         */
/* Input:  see interface                                                   */ 
/*                                                                      */
/* Output:                                                              */
/*                                                                         */
/* DRS Functions called:                                                   */
/* none                                                                    */ 
/*                                                                         */ 
/* Pseudocode:                                                             */
/* Missing                                                                 */ 
/*                                                                         */ 
/* 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_writeframe.h>
#include <flames_readframe.h>
#include <flames_freeordpos.h>
#include <flames_slitdivide.h>
#include <flames_slitdivide.h>
#include <flames_mainslitdivide.h>
#include <flames_newmatrix.h>
#include <flames_readordpos.h>
#include <flames_readslitflats.h>
#include <flames_allocframe.h>
#include <flames_freeslitflats.h>
#include <flames_freeframe.h>

/* Here goes the main() */
int flames_mainslitdivide(const cpl_frameset *NORMSLITCAT,
                          const char *INFRAMENAME,
                          const char *OUTFRAMENAME,
                          const char *MYORDTAB)
{
    allslitflats *slitflats=0;
    orderpos *ordpos=0;
    flames_frame *inframe=0;
    flames_frame *outframe=0;
    int status=0;
    int actvals=0;
    //char incat[CATREC_LEN+1];
    const cpl_frameset *incat;
    char inframename[CATREC_LEN+1];
    char outframename[CATREC_LEN+1];
    char ordername[CATREC_LEN+1];
    int32_t i=0;
    int32_t iframe=0;

    //memset(incat, '\0', CATREC_LEN+1);
    memset(inframename, '\0', CATREC_LEN+1);
    memset(outframename, '\0', CATREC_LEN+1);
    memset(ordername, '\0', CATREC_LEN+1);

    /* allocate memory for the structures */
    slitflats = calloc(1, sizeof(allslitflats));
    ordpos = calloc(1, sizeof(allslitflats));
    inframe = calloc(1, sizeof(flames_frame));
    outframe = calloc(1, sizeof(flames_frame));

    /* enter the MIDAS environment */
    SCSPRO("slitdivide");

    /* read the NORMSLITCAT keyword to know the name of the catalog file
     containing the list of int32_t slit FF frames */
    if ((status=SCKGETC_fs(NORMSLITCAT, 1, 79, &actvals, &incat))
                    != 0) {
        /* the keyword seems undefined, protest... */
        free(slitflats);
        free(ordpos);
        free(inframe);
        free(outframe);
        return flames_midas_fail();
    }

    /* read the INFRAMENAME keyword to know the name of the input frame */
    if ((status=SCKGETC(INFRAMENAME, 1, 79, &actvals, inframename))
                    != 0) {
        /* the keyword seems undefined, protest... */
        free(slitflats);
        free(ordpos);
        free(inframe);
        free(outframe);
        return flames_midas_fail();
    }

    /* read the OUTFRAMENAME keyword to know the name of the output frame */
    if ((status=SCKGETC(OUTFRAMENAME, 1, 79, &actvals, outframename))
                    != 0) {
        /* the keyword seems undefined, protest... */
        free(slitflats);
        free(ordpos);
        free(inframe);
        free(outframe);
        return flames_midas_fail();
    }

    /* read the OUTFRAMENAME keyword to know the name of the output frame */
    if ((status=SCKGETC(MYORDTAB, 1, 79, &actvals, ordername))
                    != 0) {
        /* the keyword seems undefined, protest... */
        free(slitflats);
        free(ordpos);
        free(inframe);
        free(outframe);
        return flames_midas_fail();
    }

    /* initialise the ordpos structure from the dummy table descriptors */
    if ((status = readordpos(ordername, ordpos)) != NOERR) {
        /* something went wrong in the initialisation */
        free(slitflats);
        free(ordpos);
        free(inframe);
        free(outframe);
        return flames_midas_fail();
    }

    /* initialise the slitflats structure from disk */
    if ((status = readslitflats(incat, slitflats)) != 0) {
        /* problems reading slitflats members from disk */
        free(slitflats);
        free(ordpos);
        free(inframe);
        free(outframe);
        return flames_midas_fail();
    }
    /* correct for the ycorrection, if present */
    if (ordpos->corrected=='t') {
        for (iframe=0; iframe<=(slitflats->nflats-1);iframe++)
            slitflats->slit[iframe].yshift -= ordpos->ycorrection;
    }

    /* read the input frame from disk */
    if ((status = readframe(inframe, inframename)) != 0) {
        /* problems reading the input frame from disk */
        free(slitflats);
        free(ordpos);
        free(inframe);
        free(outframe);
        return flames_midas_fail();
    }

    /* does the order table match the frame chip? */
    if((ordpos->chipchoice != inframe->chipchoice) ||
                    (ordpos->chipchoice != slitflats->chipchoice)) {
        /* no, it doesn't */
        SCTPUT("Error: chip mismatch between frames and order table");
        free(slitflats);
        free(ordpos);
        free(inframe);
        free(outframe);
        return flames_midas_fail();
    }

    /* I am not quite convinced as to where the firstorder and lastorder
     ought to be initialised in a frame, at the moment I set them here to 
     be equal to those in ordpos, but this is still TBD; perhaps 
     everything should just use firstorder and lastorder in ordpos, and 
     discard the others or initialise them from ordpos. */
    inframe->firstorder = ordpos->firstorder;
    inframe->lastorder = ordpos->lastorder;
    inframe->tab_io_oshift = ordpos->tab_io_oshift;

    /* does the input frame match the slitflats structure? */
    if (inframe->subrows != slitflats->subrows ||
                    inframe->subcols != slitflats->subcols ||
                    inframe->substartx != slitflats->substartx ||
                    inframe->substarty != slitflats->substarty ||
                    inframe->substepx != slitflats->substepx ||
                    inframe->substepy != slitflats->substepy ||
                    inframe->ron != slitflats->ron ||
                    inframe->gain != slitflats->gain) {
        SCTPUT("Mismatch between slit FF frames and input frame");
        free(outframe);
        return flames_midas_fail();
    }

    /* copy the (relevant) scalars from inframe to outframe */
    outframe->subrows = inframe->subrows;
    outframe->subcols = inframe->subcols;
    /*
  outframe->chiprows = inframe->chiprows;
  outframe->chipcols = inframe->chipcols;
  outframe->subfirstrow = inframe->subfirstrow;
  outframe->subfirstcol = inframe->subfirstcol;
     */
    outframe->maxfibres = inframe->maxfibres;
    outframe->substartx = inframe->substartx;
    outframe->substarty = inframe->substarty;
    outframe->substepx = inframe->substepx;
    outframe->substepy = inframe->substepy;
    /*
  outframe->chipstartx = inframe->chipstartx;
  outframe->chipstarty = inframe->chipstarty;
  outframe->chipstepx = inframe->chipstepx;
  outframe->chipstepy = inframe->chipstepy;
     */
    outframe->chipchoice = inframe->chipchoice;
    outframe->ron = inframe->ron;
    outframe->gain = inframe->gain;
    outframe->nflats = inframe->nflats;
    /*
  outframe->Extract_Window = inframe->Extract_Window;
  outframe->sigma = inframe->sigma;
     */
    outframe->firstorder = inframe->firstorder;
    outframe->lastorder = inframe->lastorder;
    outframe->tab_io_oshift = inframe->tab_io_oshift;
    /* allocate memory for internal arrays */
    if ((status = allocframe(outframe)) != NOERR) {
        /* I could not allocate memory for outframe */
        return flames_midas_fail();
    }
    /* copy relevant arrays that must be copied equal from inframe to outframe */
    if (inframe->maxfibres>0){
        for (i=0; i<=inframe->maxfibres-1; i++) {
            outframe->fibremask[i] = inframe->fibremask[i];
        }
    }
    if (inframe->nflats>0) {
        for (i=0; i<=inframe->nflats-1; i++) {
            outframe->yshift = inframe->yshift;
        }
    }

    /* do the actual work... */
    if ((status = slitdivide(slitflats, ordpos, inframe, outframe)) != NOERR) {
        /* something went wrong in slitdivide */
        return flames_midas_fail();
    }

    /* write outframe to disk */
    if ((status = writeframe(outframe, outframename, inframename)) != NOERR) {
        /* something went wrong in writeframe */
        return flames_midas_fail();
    }

    /* free dynamically allocated memory */
    if ((status = freeslitflats(slitflats)) != NOERR) {
        /* something went wrong in freeslitflats */
        return flames_midas_fail();
    }
    free(slitflats);
    if ((status = freeordpos(ordpos)) != NOERR) {
        /* something went wrong in freeordpos */
        return flames_midas_fail();
    }
    free(ordpos);
    if ((status = freeframe(inframe)) != NOERR) {
        /* something went wrong in freeframe */
        return flames_midas_fail();
    }
    free(inframe);
    if ((status = freeframe(outframe)) != NOERR) {
        /* something went wrong in freeframe */
        return flames_midas_fail();
    }
    free(outframe);

    return(SCSEPI());

}
