/* 
 * This file is part of the KMOS Pipeline
 * Copyright (C) 2002,2003 European Southern Observatory
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

/*-----------------------------------------------------------------------------
                                Includes
 -----------------------------------------------------------------------------*/

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

#include <cpl.h>

#include "kmo_dfs.h"

/*-----------------------------------------------------------------------------
                            Functions prototypes
 -----------------------------------------------------------------------------*/

static int kmos_gen_reflines_save(cpl_table *, const cpl_parameterlist *, 
        cpl_frameset *);

static int kmos_gen_reflines_create(cpl_plugin *);
static int kmos_gen_reflines_exec(cpl_plugin *);
static int kmos_gen_reflines_destroy(cpl_plugin *);
static int kmos_gen_reflines(const cpl_parameterlist *, cpl_frameset *);

/*-----------------------------------------------------------------------------
 *                          Static variables
 *----------------------------------------------------------------------------*/

static char kmos_gen_reflines_description[] =
"This recipe is used to generate the REFLINES calibration file.\n"
"The sof file contains the name of the input ASCII file\n"
"tagged with "KMOS_GEN_REFLINES_RAW".\n"
"The ASCII file must contain seven columns like the output of:\n"
"    dtfits -d -s ' ' kmos_wave_ref_table.fits\n"
"The six column titles are:\n"
"FILTER|DETECTOR|WAVELENGTH|REFERENCE| OFFSET|  RANGE|    CUT\n"
"The entries are like:\n"
"    HK       3   1.79196        0    210     20    577\n"
"    HK       3   2.25365        4    427     15     71\n"
"    HK       3   2.06129       -1   1313     50    140\n"
"    HK       3   2.32666        4    594     15     32\n"
"    IZ       1  0.912547       -1    775     80   4000\n"
"    IZ       1  0.966044       -1   1150     80   2000\n"
"    IZ       1   1.04729       -1   1730     80    200\n"
"    IZ       1   1.06765        2    128     40     80\n"
"...\n"
"This recipe produces 1 file:\n"
"First product:     the table with the configuration for the model.\n" ;

/*----------------------------------------------------------------------------*/
/**
 * @defgroup kmos_gen_reflines  REFLINES calibration file generation
 */
/*----------------------------------------------------------------------------*/

/**@{*/

/*-----------------------------------------------------------------------------
                                Functions code
 -----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/**
  @brief    Build the list of available plugins, for this module. 
  @param    list    the plugin list
  @return   0 if everything is ok, -1 otherwise

  Create the recipe instance and make it available to the application using the 
  interface. This function is exported.
 */
/*----------------------------------------------------------------------------*/
int cpl_plugin_get_info(cpl_pluginlist *list)
{
    cpl_recipe *recipe = cpl_calloc(1, sizeof *recipe);
    cpl_plugin *plugin = &recipe->interface;

    cpl_plugin_init(plugin,
            CPL_PLUGIN_API,
            KMOS_BINARY_VERSION,
            CPL_PLUGIN_TYPE_RECIPE,
            "kmos_gen_reflines",
            "Create REFLINES calibration file",
            kmos_gen_reflines_description,
            "Yves Jung",
            "usd-help@eso.org",
            kmos_get_license(),
            kmos_gen_reflines_create,
            kmos_gen_reflines_exec,
            kmos_gen_reflines_destroy);

    cpl_pluginlist_append(list, plugin);

    return 0;
}
/*----------------------------------------------------------------------------*/
/**
  @brief    Setup the recipe options    
  @param    plugin  the plugin
  @return   0 if everything is ok

  Defining the command-line/configuration parameters for the recipe.
 */
/*----------------------------------------------------------------------------*/
static int kmos_gen_reflines_create(cpl_plugin *plugin)
{
    cpl_recipe *recipe;
    cpl_parameter *p;

    /* Check that the plugin is part of a valid recipe */
    if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
        recipe = (cpl_recipe *)plugin;
    else
        return -1;

    /* Create the parameters list in the cpl_recipe object */
    recipe->parameters = cpl_parameterlist_new();

    /* Fill the parameters list */

    return 0 ;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Execute the plugin instance given by the interface
  @param    plugin  the plugin
  @return   0 if everything is ok
 */
/*----------------------------------------------------------------------------*/
static int kmos_gen_reflines_exec(cpl_plugin *plugin)
{
    cpl_recipe  *recipe;

    /* Get the recipe out of the plugin */
    if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
        recipe = (cpl_recipe *)plugin;
    else return -1;

    return kmos_gen_reflines(recipe->parameters, recipe->frames);
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Destroy what has been created by the 'create' function
  @param    plugin  the plugin
  @return   0 if everything is ok
 */
/*----------------------------------------------------------------------------*/
static int kmos_gen_reflines_destroy(cpl_plugin *plugin)
{
    cpl_recipe *recipe;

    /* Get the recipe out of the plugin */
    if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE)
        recipe = (cpl_recipe *)plugin;
    else return -1 ;

    cpl_parameterlist_delete(recipe->parameters);
    return 0 ;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    The FITS file creation occurs here 
  @param    framelist   the frames list
  @return   0 iff everything is ok
  The recipe expects a text file and will create a FITS file out of it. 
 */
/*----------------------------------------------------------------------------*/
static int kmos_gen_reflines(
        const cpl_parameterlist *   parlist,
        cpl_frameset            *   framelist)
{
    FILE            *   in ;
    char                line[1024];
    cpl_frame       *   cur_frame ;
    const char      *   cur_fname ;
    int                 nentries ;
    char                band[1024] ;
    int                 det, ref, offset, range, cut ;
    double              wave ;
    cpl_table       *   tab ;
    int                 i ;

    /* Retrieve input parameters */

    /* Identify the RAW and CALIB frames in the input frameset */
    if (kmo_dfs_set_groups(framelist, "kmos_gen_reflines") != 1) {
        cpl_msg_error(__func__, "Cannot identify RAW and CALIB frames") ;
        cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
        return -1 ;
    }
  
    /* Get the config file name */
    cur_frame = cpl_frameset_get_position(framelist, 0) ;
    cur_fname = cpl_frame_get_filename(cur_frame) ;

    /* Open the file */
    if ((in = fopen(cur_fname, "r")) == NULL) {
        cpl_msg_error(__func__, "Could not open %s", cur_fname) ;
        cpl_error_set(__func__, CPL_ERROR_ILLEGAL_INPUT) ;
        return -1 ;
    }

    /* Count number of entries */
    nentries = 0 ;
    while (fgets(line, 1024, in) != NULL) {
        if (line[0] != '#' && sscanf(line, "%s %d %lg %d %d %d %d", 
                    band, &det, &wave, &ref, &offset, &range, &cut) == 7)  
            nentries++ ;
    }
    if (nentries == 0) {
        cpl_msg_error(__func__, "No valid entry in the file") ;
        fclose(in) ;
        return -1 ;
    }
        
    /* Create the output table */
    tab = cpl_table_new(nentries) ;
    cpl_table_new_column(tab, "FILTER", CPL_TYPE_STRING) ;
    cpl_table_new_column(tab, "DETECTOR", CPL_TYPE_INT) ;
    cpl_table_new_column(tab, "WAVELENGTH", CPL_TYPE_DOUBLE) ;
    cpl_table_new_column(tab, "REFERENCE", CPL_TYPE_INT) ;
    cpl_table_new_column(tab, "OFFSET", CPL_TYPE_INT) ;
    cpl_table_new_column(tab, "RANGE", CPL_TYPE_INT) ;
    cpl_table_new_column(tab, "CUT", CPL_TYPE_INT) ;
    
    /* Fill the table */
    i = 0 ;
    rewind(in) ;
    while (fgets(line, 1024, in) != NULL) {
        if (line[0] != '#' && sscanf(line, "%s %d %lg %d %d %d %d", 
                    band, &det, &wave, &ref, &offset, &range, &cut) == 7) {
            cpl_table_set_string(tab, "FILTER", i, band) ;
            cpl_table_set_int(tab, "DETECTOR", i, det) ;
            cpl_table_set_double(tab, "WAVELENGTH", i, wave) ;
            cpl_table_set_int(tab, "REFERENCE", i, ref) ;
            cpl_table_set_int(tab, "OFFSET", i, offset) ;
            cpl_table_set_int(tab, "RANGE", i, range) ;
            cpl_table_set_int(tab, "CUT", i, cut) ;
            i++ ;
        }
    }
    fclose(in) ;
   
    /* Save the table */
    cpl_msg_info(__func__, "Saving the table with %d rows", nentries) ;
    if (kmos_gen_reflines_save(tab, parlist, framelist) == -1) {
        cpl_msg_error(__func__, "Cannot write the table") ;
        cpl_table_delete(tab) ;
        return -1 ;
    }
    cpl_table_delete(tab) ;
    return 0 ;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Save the product of the recipe
  @param    out_table   the table 
  @param    parlist     the input list of parameters
  @param    set         the input frame set
  @return   0 if everything is ok, -1 otherwise
 */
/*----------------------------------------------------------------------------*/
static int kmos_gen_reflines_save(
        cpl_table               *   out_table,
        const cpl_parameterlist *   parlist,
        cpl_frameset            *   set)
{
    cpl_propertylist    *   plist ;
    cpl_propertylist    *   plist_ext ;

    plist = cpl_propertylist_new();
    cpl_propertylist_append_string(plist, "INSTRUME", "KMOS") ;
    cpl_propertylist_append_string(plist, CPL_DFS_PRO_CATG, "REF_LINES") ;
    plist_ext = cpl_propertylist_new();
    cpl_propertylist_append_string(plist_ext, "EXTNAME", "LIST") ;

    if (cpl_dfs_save_table(set, NULL, parlist, set, NULL, out_table,
                plist_ext, "kmos_gen_reflines", plist, NULL, 
                PACKAGE "/" PACKAGE_VERSION,
                "kmos_gen_reflines.fits") != CPL_ERROR_NONE) {
        cpl_msg_error(__func__, "Cannot save the table") ;
    cpl_propertylist_delete(plist) ;
    cpl_propertylist_delete(plist_ext) ;
        return -1 ;
    }
    cpl_propertylist_delete(plist) ;
    cpl_propertylist_delete(plist_ext) ;
    
    /* Return */
    return 0 ;
}
