/*===========================================================================
  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  : mainshift.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 <flames_writeallff.h>
#include <flames_readallff.h>
#include <flames_initallflatsout.h>
#include <flames_mainshift.h>
#include <flames_stripfitsext.h>
#include <flames_freeallflats.h>

#include <flames_midas_def.h>
#include <flames_uves.h>
#include <flames_newmatrix.h>
#include <flames_shiftcommon.h>
#include <flames_shiftall.h>
#include <flames_shift_all_FF.h>
#include <flames_freeordpos.h>
#include <flames_readordpos.h>
#include <uves_msg.h>

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>

int flames_mainshift(const cpl_frameset *INFIBREFFCAT,
                     cpl_frameset **OUTFIBREFFCAT,
                     const char *MYORDTAB,
                     const char *BASENAME,
                     const double *YSHIFT)
{
  allflats *allflatsin=0;
  allflats *allflatsout=0;
  orderpos *ordpos=0;

  int status=0;
  int actvals=0;
  int unit=0;
  int null=0;
  //char incatname[CATREC_LEN+1];
  const cpl_frameset *incatname;
  //char outcatname[CATREC_LEN+1];
  cpl_frameset **outcatname;
  char filename[CATREC_LEN+1];
  char ordername[CATREC_LEN+1];
  char basename[CATREC_LEN+1];
  char output[CATREC_LEN+1];
  double yshift=0;

  //memset(incatname, 0, CATREC_LEN+1);
  //memset(outcatname, 0, CATREC_LEN+1);
  memset(filename, 0, CATREC_LEN+1);
  memset(ordername, 0, CATREC_LEN+1);
  memset(basename, 0, CATREC_LEN+1);
  memset(output, 0, CATREC_LEN+1);

  uves_msg("sh1");
  /* allocate pointers */
  allflatsin = (allflats *) calloc(1, sizeof(allflats));
  allflatsout = (allflats *) calloc(1, sizeof(allflats));
  ordpos = (orderpos *) calloc(1, sizeof(orderpos));

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

  SCTPUT("mainshift starting...");

  uves_msg("sh2");
  /* read the INFIBREFFCAT keyword to know the name of the catalog file
     containing the list of unshifted fibre FF frames */
  if ((status=SCKGETC_fs(INFIBREFFCAT, 1, CATREC_LEN, &actvals, &incatname))
      != 0) {
     /* the keyword seems undefined, protest... */
     free(allflatsin);
     free(allflatsout);
     free(ordpos);
    return flames_midas_fail();
  }

  /* read the OUTFIBREFFCAT keyword to know the name of the catalog file
     to contain the list of shifted fibre FF frames */
  if ((status=SCKGETC_fsp(OUTFIBREFFCAT, 1, CATREC_LEN, &actvals, &outcatname))
      != 0) {
    /* the keyword seems undefined, protest... */
     free(allflatsin);
     free(allflatsout);
     free(ordpos);
    return flames_midas_fail();
  }

  uves_msg("sh3");
  /* read the MYORDTAB keyword to know the order table to open */
  if ((status=SCKGETC(MYORDTAB, 1, CATREC_LEN, &actvals, ordername))
      != 0) {
    /* the keyword seems undefined, protest... */
     free(allflatsin);
     free(allflatsout);
     free(ordpos);
    return flames_midas_fail();
  }

  /* read the BASENAME keyword to know the base file name of the newly
     produced FF frames */
  if ((status=SCKGETC(BASENAME, 1, CATREC_LEN, &actvals, filename))
      != 0) {
    /* the keyword seems undefined, protest... */
     free(allflatsin);
     free(allflatsout);
     free(ordpos);
    return flames_midas_fail();
  }

  /* strip filename of the .fits extension, if it has one */
  if ((status = stripfitsext(filename, basename)) != NOERR) {
    /* error stripping extension */
     free(allflatsin);
     free(allflatsout);
     free(ordpos);
    return flames_midas_fail();
  }

  /* read the YSHIFT keyword to know the requested y shift */
  if ((status=SCKRDD(YSHIFT, 1, 1, &actvals, &yshift, &unit, &null))
      != 0) {
    /* the keyword seems undefined, protest... */
     free(allflatsin);
     free(allflatsout);
     free(ordpos);
    return flames_midas_fail();
  }

  SCTPUT("reading unshifted FF frames...");

  /* read allflatsin from files */
  if ((status = readallff(incatname, allflatsin)) != NOERR) {
    /* error reading allflatsin */
     free(allflatsin);
     free(allflatsout);
     free(ordpos);
    return flames_midas_fail();
  }
 uves_msg("sh5");

  /* is this fibre FF frames set shiftable? */
  if (allflatsin->shiftable != 'y') {
    sprintf(output, "The fibre FF set  not slit-flatfielded");
    SCTPUT(output);
     free(allflatsin);
     free(allflatsout);
     free(ordpos);
    return flames_midas_fail();
  }

  SCTPUT("reading order/fibre position information...");
  /* initialise the ordpos structure from the dummy table descriptors */
  if((status = readordpos(ordername, ordpos)) != NOERR) {
    /* something went wrong in the initialisation */
    free(allflatsout);
    return flames_midas_fail();
  }
 uves_msg("sh6");

  /* check whether chip choices match */
  if (ordpos->chipchoice != allflatsin->chipchoice) {
    /* no, they don't match */
    SCTPUT("Error: chip mismatch between frames and order table");
     free(allflatsin);
     free(allflatsout);
     free(ordpos);
    return flames_midas_fail(); 
  }   

  SCTPUT("allocate and initialise shifted FF frames...");
 uves_msg("sh7");

  /* initialise the *allflatsout structure */
  if ((status=initallflatsout(allflatsin, allflatsout)) != NOERR) {
     free(allflatsin);
     free(allflatsout);
     free(ordpos);
    return flames_midas_fail();
  }

  SCTPUT("starting actual shifting...");

  /* shift allflatsin and put result in allflatsout */
  if ((status = shift_all_FF(allflatsin, ordpos, yshift, allflatsout)) 
      != NOERR) {
    /* problems shifting */
     free(allflatsin);
     free(allflatsout);
     free(ordpos);
    return flames_midas_fail();
  }
 uves_msg("sh8");

  SCTPUT("write shifted FF frames to disk...");

  /* write allflatsout to disk */
  if ((status = writeallff(allflatsout, basename, outcatname)) != NOERR) {
    /* problems dumping structure to disk */
     free(allflatsin);
     free(allflatsout);
     free(ordpos);
    return flames_midas_fail();
  }

  SCTPUT("clean up memory...");

  /* time to free memory */
  if ((status = freeallflats(allflatsin)) != NOERR) {
    /* problems freing allflatsin internal array members*/
     free(allflatsin);
     free(allflatsout);
     free(ordpos);
    return flames_midas_fail();
  }
  free(allflatsin);
  if ((status = freeallflats(allflatsout)) != NOERR) {
    /* problems freing allflatsin internal array members*/
     free(allflatsout);
     free(ordpos);
    return flames_midas_fail();
  }
  free(allflatsout);
  if ((status = freeordpos(ordpos)) != NOERR) {
    /* problems freing ordpos internal array members*/
    return flames_midas_fail();
  }
  free(ordpos);
 uves_msg("sh9");

  SCTPUT("mainshift done...");

  /* bye bye */
  return(SCSEPI());

}
