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

}
