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

    /* 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...");

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

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

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

    /* 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...");

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

    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);

    SCTPUT("mainshift done...");

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

}
