/*
 * 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_object_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_objnod_ini_by_cpl.h"
#include "sinfo_pro_types.h"
#include "sinfo_hidden.h"
#include "sinfo_globals.h"
#include "sinfo_functions.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 objnod structure
 *
 * TBD
 */



/*-------------------------------------------------------------------------*/
/**
  @name     parse_object_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_objnod(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_objnod_free(&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;
   int i=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);

   sinfo_contains_frames_type(sof,stk,PRO_NODDING_STACKED);
   nstk = cpl_frameset_get_size(*stk);

   if (nstk == 0) {
      sinfo_contains_frames_type(sof,stk,PRO_PSF_CALIBRATOR_STACKED);
      nstk = cpl_frameset_get_size(*stk);
   }
   if (nstk == 0) {
      sinfo_contains_frames_type(sof,stk,PRO_PUPIL_LAMP_STACKED);
      nstk = cpl_frameset_get_size(*stk);
   }
   if (nstk == 0) {
        sinfo_msg_error( "Cannot find good frames") ;
        (*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!");
     (*status)++;
     return ;
   }

   /* 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,  OBJNOD_OUT_FILENAME);
   strcpy(cfg -> maskname, OBJNOD_OUT_BPMAP);
   strcpy(cfg -> med_cube_name, OBJNOD_OUT_MED_CUBE);


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

   if(NULL != cpl_frameset_find(sof,PRO_WAVE_MAP)) {
     frame = cpl_frameset_find(sof,PRO_WAVE_MAP);
     strcpy(cfg -> wavemap, cpl_frame_get_filename(frame));
   } else {
     sinfo_msg("Frame %s not found!", PRO_WAVE_MAP);
     sinfo_msg_error("%s", (char* ) cpl_error_get_message());
     (*status)++;
     return ;
   }

   if(NULL != cpl_frameset_find(sof,PRO_MASTER_FLAT_LAMP)) {
     frame = cpl_frameset_find(sof,PRO_MASTER_FLAT_LAMP);
     strcpy(cfg -> mflat, cpl_frame_get_filename(frame));
   } else {
     sinfo_msg("Frame %s not found!", PRO_MASTER_FLAT_LAMP);
     sinfo_msg_error("%s", (char* ) cpl_error_get_message());
     (*status)++;
     return ;
   }

   if(NULL != cpl_frameset_find(sof,PRO_STACK_SKY_DIST)) {
     frame = cpl_frameset_find(sof,PRO_STACK_SKY_DIST);
     strcpy(cfg -> sky_dist, cpl_frame_get_filename(frame));
   } else {
     sinfo_msg_warning("Frame %s not found!", PRO_STACK_SKY_DIST);
     strcpy(cfg -> sky_dist,"no_sky");
   }

   if(NULL != cpl_frameset_find(sof,PRO_STACK_MFLAT_DIST)) {
     frame = cpl_frameset_find(sof,PRO_STACK_MFLAT_DIST);
     strcpy(cfg -> mflat_dist, cpl_frame_get_filename(frame));
   } else {
     strcpy(cfg -> mflat_dist, "not_found");
     sinfo_msg("Frame %s not found!", PRO_STACK_MFLAT_DIST);
   }


   if(NULL != cpl_frameset_find(sof,PRO_STACK_MFLAT_DITHER_DIST)) {
     frame = cpl_frameset_find(sof,PRO_STACK_MFLAT_DITHER_DIST);
     strcpy(cfg -> mflat_dither_dist, cpl_frame_get_filename(frame));
   } else {
     strcpy(cfg -> mflat_dither_dist, "not_found");
     sinfo_msg("Frame %s not found!", PRO_STACK_MFLAT_DITHER_DIST);
   }


   if(cfg -> northsouthInd) {

     if(NULL != cpl_frameset_find(sof,PRO_SLITLETS_DISTANCE)) {
       frame = cpl_frameset_find(sof,PRO_SLITLETS_DISTANCE);
       strcpy(cfg -> distlist, cpl_frame_get_filename(frame));
     } else {
       sinfo_msg("Frame %s not found!", PRO_SLITLETS_DISTANCE);
       (*status)++;
       return ;
     }

   } else {

     if(NULL != cpl_frameset_find(sof,PRO_SLIT_POS)) {
       frame = cpl_frameset_find(sof,PRO_SLIT_POS);
       strcpy(cfg -> poslist, cpl_frame_get_filename(frame));
     } else {
       sinfo_msg("Frame %s not found!", PRO_SLIT_POS);
       (*status)++;
       return ;
     }

   }
   if(cfg -> halocorrectInd) {
     if(NULL != cpl_frameset_find(sof,PRO_HALO_SPECT)) {
       frame = cpl_frameset_find(sof,PRO_HALO_SPECT);
       strcpy(cfg -> halospectrum, cpl_frame_get_filename(frame));
     } else {
       sinfo_msg("Frame %s not found!", PRO_HALO_SPECT);
       (*status)++;
       return ;
     }

   }
   if(NULL != cpl_frameset_find(sof, PRO_REF_ATM_REF_CORR))
   {
       frame = cpl_frameset_find(sof, PRO_REF_ATM_REF_CORR);
       strcpy(cfg->polyshiftname, cpl_frame_get_filename(frame));
   } else
   {
       sinfo_msg("Frame %s not found, shift due atmospheric refraction "
    		   "would not be applied!", PRO_REF_ATM_REF_CORR);
       cfg->polyshiftname[0] = 0;
//       (*status)++;
   }
   /*
   sinfo_msg("cfg -> wavemap  %s",cfg -> wavemap);
   sinfo_msg("cfg -> poslist  %s",cfg -> poslist);
   sinfo_msg("cfg -> firstCol %s",cfg -> firstCol);
   */
   return;
}


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

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

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

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

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objnod.kernel_type");
   strcpy(cfg -> kernel_type, 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.objnod.n_coeffs");
   cfg -> ncoeffs = cpl_parameter_get_int(p);

   cfg -> nrows = SINFO_RESAMP_NROWS;
   return ;
}

static void
parse_section_calibration(object_config * cfg)
{
  cfg -> halocorrectInd=0;


}

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

   return ;
}

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

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

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objnod.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.objnod.low_rejection");
   cfg -> loReject = cpl_parameter_get_double(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.objnod.high_rejection");
   cfg -> hiReject = cpl_parameter_get_double(p);

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

}

/*-----------------------------------------------------------------*/
void
sinfo_objnod_free(object_config ** cfg) {
  if(*cfg != NULL) {
    for(int i=0;i<(*cfg)->nframes;i++) {
      if((*cfg)->framelist[i]!=NULL) {
    cpl_free((*cfg)->framelist[i]);
    (*cfg)->framelist[i]=NULL;
      }
    }
    if((*cfg)->framelist != NULL) {
      cpl_free((*cfg)->framelist);
      (*cfg)->framelist=NULL;
    }
    sinfo_object_cfg_destroy (*cfg);
    *cfg=NULL;
  }
  return;
}
/**@}*/
