/*
 * This file is part of the ESO SINFONI Pipeline
 * Copyright (C) 2004,2005 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, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
 */

/*----------------------------------------------------------------------------
   
   File name    :   sinfo_objspider_ini_by_cpl.c
   Author       :   Andrea Modigliani
   Created on   :   May 22, 2004
   Description  :   object cube creation cpl input handling for SPIFFI

 ---------------------------------------------------------------------------*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif
/*---------------------------------------------------------------------------
                                Includes
 ---------------------------------------------------------------------------*/
#include <string.h>
#include "sinfo_objspider_ini_by_cpl.h"
#include "sinfo_functions.h"
#include "sinfo_pro_types.h"
#include "sinfo_hidden.h"
#include "sinfo_cpl_size.h"

#include "sinfo_file_handling.h"
/*---------------------------------------------------------------------------
                    Functions private to this module
 ---------------------------------------------------------------------------*/

static void 
parse_section_frames(object_config *,
                     cpl_frameset* sof, cpl_frameset**stk, int* status);
static void 
parse_section_jittering(object_config *, cpl_parameterlist * cpl_cfg);
static void 
parse_section_resampling(object_config *, cpl_parameterlist * cpl_cfg);
static void 
parse_section_calibration(object_config *);
static void 
parse_section_cubecreation(object_config *, cpl_parameterlist * cpl_cfg);
static void 
parse_section_finetuning(object_config *, cpl_parameterlist * cpl_cfg);
static void 
parse_section_skyextraction(object_config *, cpl_parameterlist * cpl_cfg);
/**@{*/
/**
 * @addtogroup sinfo_rec_jitter Blackboard to objspider structure
 *
 * TBD
 */



/*-------------------------------------------------------------------------*/
/**
  @name     parse_objspider_ini_file
  @memo     Parse a ini_name.ini file and create a blackboard.
  @param    ini_name    Name of the ASCII file to parse.
  @return   1 newly allocate object_config blackboard structure.
  @doc

  The requested ini file is parsed and a blackboard object is created, then
  updated accordingly. Returns NULL in case of error.
 */
/*--------------------------------------------------------------------------*/

object_config * 
sinfo_parse_cpl_input_objspider(cpl_parameterlist * cpl_cfg,cpl_frameset* sof,
              cpl_frameset** stk)
{
   object_config   *  cfg = sinfo_object_cfg_create();
   int status=0;
   /*
    * Perform sanity checks, fill up the structure with what was
    * found in the ini file
    */

   
   parse_section_resampling   (cfg, cpl_cfg);
   parse_section_calibration  (cfg);
   parse_section_cubecreation (cfg, cpl_cfg);
   parse_section_finetuning   (cfg, cpl_cfg); 
   parse_section_skyextraction(cfg, cpl_cfg); 
   parse_section_jittering    (cfg, cpl_cfg);
   parse_section_frames       (cfg, sof,stk,&status);
   if (status > 0) {
                sinfo_msg_error("parsing cpl input");
                sinfo_object_cfg_destroy(cfg);
                cfg = NULL ;
                return NULL ;
   }
 
   return cfg ;
}

static void      
parse_section_frames(object_config * cfg, 
             cpl_frameset* sof,
                     cpl_frameset** stk,
                     int* status)
{
   int                     nraw_good =0;



   int nframes=0;
   int nraw=0;
   cpl_frame* frame   = NULL;
   int nstk=0;
   cpl_size             *   labels=NULL ;
   cpl_size                 nlabels=0 ;
   cpl_frameset    *   cur_set=NULL ;
   cpl_frame       *   cur_frame=NULL ;
   char * tag=NULL;
   int i=0;
   int wave_map=0;
   int pos_slit=0;
   int first_col=0;
   int halo_sp=0;
   char spat_res[FILE_NAME_SZ];
   char lamp_status[FILE_NAME_SZ];
   char band[FILE_NAME_SZ];
   int ins_set=0;

   nframes = cpl_frameset_get_size(sof);

   /* Get the raw and the calibration files */
   /* Labelise the input frames according to their tags */
   labels = cpl_frameset_labelise(sof, sinfo_compare_tags,&nlabels );
   if (labels == NULL) {
     sinfo_msg_error( "Cannot labelise the input frames") ;
     (*status)++;
     return ;
   }
   if (nlabels == 1) {
      /* Only one label - all images are objects observations */
      /* Verify that it is really an observation */
      cur_frame = cpl_frameset_get_frame(sof, 0) ;
      tag = (char*)cpl_frame_get_tag(cur_frame) ;
      if (sinfo_is_stack(tag)) {
    *stk = cpl_frameset_duplicate(sof) ;
    nstk++;
      }
   } else {
     /* For each label */
     for (i=0 ; i<nlabels ; i++) {
       cur_set = cpl_frameset_extract(sof, labels, i) ;
       cur_frame = cpl_frameset_get_frame(cur_set, 0) ;
       tag = (char*)cpl_frame_get_tag(cur_frame) ;
       if (sinfo_is_stack(tag) == 1) {
     /* Stacked frame */
     *stk = cpl_frameset_duplicate(cur_set) ;
     nstk++;
       } else if (sinfo_is_wavemap(tag)) {
     /* pos slit calibration file */
     strcpy(cfg -> wavemap,cpl_strdup(cpl_frame_get_filename(cur_frame)));
     wave_map=1;
       } else if (sinfo_is_distlist(tag)) {
     /* pos slit calibration file */
     strcpy(cfg -> poslist,cpl_strdup(cpl_frame_get_filename(cur_frame)));
     pos_slit=1;
       } else if (sinfo_is_firstcol(tag)) { 
     /* first col calibration file */
     strcpy(cfg -> firstCol,cpl_strdup(cpl_frame_get_filename(cur_frame)));
     first_col=1;
       } else if (sinfo_is_halosp(tag)) { 
     /* first col calibration file */
     strcpy(cfg->halospectrum,cpl_strdup(cpl_frame_get_filename(cur_frame)));
     halo_sp=1;
       }
       cpl_frameset_delete(cur_set) ;
     }
   }
   cpl_free(labels) ;
   if (nstk == 0) {
     sinfo_msg_error( "Cannot find good input frames") ;
     (*status)++;
     return ;
   }

   if (wave_map == 0) {
     sinfo_msg_error( "Cannot find wave map");
     (*status)++;
     return ;
   }
   if (pos_slit == 0) {
     sinfo_msg_error( "Cannot find pos slit") ;
     (*status)++;
     return ;
   }
   if (first_col == 0) {
     sinfo_msg_error( "Cannot find first col") ;
     (*status)++;
     return ;
   }


   /* TEMPORALLY COMMENTED OUT */
   nraw    = cpl_frameset_get_size(*stk);
   /* Test if the rawframes have been found */
   if (nraw < 1) {
     sinfo_msg_error("Cannot find input stacked frames in the input list") ;
     (*status)++;
     return ;
   }

   nraw    = cpl_frameset_get_size(*stk);
   if (nraw < 1) {
     sinfo_msg_error("no raw frame in input, something wrong!");
     exit(-1);
   }

   /* Allocate structures to go into the blackboard */
   cfg->framelist     = cpl_malloc(nraw * sizeof(char*));

  /* read input frames */
   for (i=0 ; i<nraw ; i++) {
     frame = cpl_frameset_get_frame(*stk,i);
     if(sinfo_file_exists((char*) cpl_frame_get_filename(frame))==1) {
       cfg->framelist[i]=cpl_strdup(cpl_frame_get_filename(frame));
       nraw_good++;
     }
     /* Store file name into framelist */
   }
   if (nraw_good < 1) {
     sinfo_msg_error("no good raw frame in input!");
     (*status)++;
     return;
   }
   /* Copy relevant information into the blackboard */
   cfg->nframes         = nraw ;

   strcpy(cfg -> outName, SKYSPIDER_OUT_FILENAME);
   strcpy(cfg -> maskname, SKYSPIDER_MASK_OUT_FILENAME);


   frame = cpl_frameset_get_frame(*stk,0);

   sinfo_get_spatial_res(frame,spat_res);
   switch(sinfo_frame_is_on(frame)) {

   case 0: 
     strcpy(lamp_status,"on");
     break;
   case 1: 
     strcpy(lamp_status,"off");
     break;
   case -1:
     strcpy(lamp_status,"undefined");
     break;
   default: 
     strcpy(lamp_status,"undefined");
     break;
   }
   sinfo_get_band(frame,band);
   sinfo_msg("Spatial resolution: %s lamp_status: %s band: %s ",
           spat_res,    lamp_status,    band);


   sinfo_get_ins_set(band,&ins_set);



   return;
}


static void     
parse_section_jittering(object_config * cfg,cpl_parameterlist * cpl_cfg)
{
  cpl_parameter* p;

  p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objspider.jitter_index");
  cfg -> jitterind = cpl_parameter_get_bool(p);

  p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objspider.size_x");
  cfg -> size_x = cpl_parameter_get_int(p);

  p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objspider.size_y");
  cfg -> size_y = cpl_parameter_get_int(p);

  p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objspider.kernel_type");
  strcpy(cfg -> kernel_type, cpl_parameter_get_string(p));

  /*
  p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objspider.mask");
  strcpy(cfg -> maskname, cpl_parameter_get_string(p));
  */

}

static void     
parse_section_resampling(object_config * cfg,cpl_parameterlist* cpl_cfg)
{
  cpl_parameter* p;

  p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objspider.n_coeffs");
  cfg -> ncoeffs = cpl_parameter_get_int(p);
  cfg -> nrows=SINFO_RESAMP_NROWS;


  return ;
}

static void     
parse_section_calibration(object_config * cfg)
{
  /*
  cpl_parameter* p;
  p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objspider.halo_correct_index");
  cfg -> halocorrectInd = cpl_parameter_get_bool(p);
  */
  cfg -> halocorrectInd=0;

  /*
  p=cpl_parameterlist_find(cpl_cfg,"sinfoni.objspider.halo_spectrum_filename");
  strcpy(cfg -> halospectrum, cpl_parameter_get_string(p));
  */

}

static void     
parse_section_cubecreation(object_config * cfg,cpl_parameterlist* cpl_cfg)
{
  cpl_parameter* p;
  p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objspider.nord_south_index");
  cfg -> northsouthInd = cpl_parameter_get_bool(p);

  /*
  p=cpl_parameterlist_find(cpl_cfg,"sinfoni.objspider.slitlets_position_list");
  strcpy(cfg -> poslist, cpl_parameter_get_string(p));
  */

  p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objspider.nslits");
  cfg -> nslits = cpl_parameter_get_int(p);

  /*
  p=cpl_parameterlist_find(cpl_cfg,"sinfoni.objspider.first_column_filename");
  strcpy(cfg -> firstCol, cpl_parameter_get_string(p));
  */

   return ;
}

static void     
parse_section_finetuning(object_config * cfg,cpl_parameterlist* cpl_cfg)
{
  cpl_parameter* p;

  p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objspider.fine_tuning_method");
  strcpy(cfg -> method, cpl_parameter_get_string(p));

  p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objspider.order");
  cfg -> order = cpl_parameter_get_int(p);

}

static void     
parse_section_skyextraction(object_config * cfg,cpl_parameterlist* cpl_cfg)
{

  cpl_parameter* p;
  p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objspider.lower_rejection");
  cfg -> loReject = (float) cpl_parameter_get_double(p);

  p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objspider.higher_rejection");
  cfg -> hiReject = (float) cpl_parameter_get_double(p);

  p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objspider.tolerance");
  cfg -> tolerance = cpl_parameter_get_int(p);

}

/*-----------------------------------------------------------------*/
void
sinfo_objspider_free(object_config * cfg) {
  cpl_free(cfg->framelist);
  sinfo_object_cfg_destroy (cfg);
  return;
}
