/*
 * 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_flat_ini_by_cpl.c
   Author       :   Andrea Modigliani
   Created on   :   May 19, 2004
   Description  :   read cpl input for SPIFFI
 ---------------------------------------------------------------------------*/
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif
/*---------------------------------------------------------------------------
                                Includes
 ---------------------------------------------------------------------------*/
#include <string.h>
#include "sinfo_flat_ini_by_cpl.h"
#include "sinfo_error.h"
#include "sinfo_hidden.h"
#include "sinfo_pro_types.h"
#include "sinfo_raw_types.h"
#include "sinfo_functions.h"
#include "sinfo_file_handling.h"
/*---------------------------------------------------------------------------
                    Functions private to this module
 ---------------------------------------------------------------------------*/
void sinfo_flat_free_alloc(flat_config * cfg);
static void 
parse_section_frames(flat_config *, cpl_frameset* sof, 
                     cpl_frameset** raw, int* status);
static void parse_section_cleanmean(flat_config *, cpl_parameterlist* cpl_cfg);
static void parse_section_badpixel(flat_config *, cpl_parameterlist* cpl_cfg);
static void parse_section_badpix(flat_config *, cpl_parameterlist* cpl_cfg);
static void parse_section_thresh(flat_config *, cpl_parameterlist* cpl_cfg);
static void     
parse_section_qclog(flat_config * cfg, cpl_parameterlist *   cpl_cfg);
/**@{*/
/**
 * @addtogroup sinfo_flat_cfg Flat manipulation functions
 *
 * TBD
 */



/**
  @name     sinfo_parse_cpl_input_flat
  @memo     Parse input frames & parameters file and create a blackboard.
  @param    cpl_cfg pointer to parameterlist
  @param    sof pointer to input set of frames
  @param    raw pointer to input set of raw frames
  @return   1 newly allocated flat_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.
 */
flat_config * 
sinfo_parse_cpl_input_flat(cpl_parameterlist* cpl_cfg, 
                                   cpl_frameset* sof, 
                                   cpl_frameset** raw)
{
        flat_config   *       cfg = sinfo_flat_cfg_create();
        int status=0;
        /*
         * Perform sanity checks, fill up the structure with what was
         * found in the ini file
         */
        parse_section_badpixel  (cfg, cpl_cfg);
        parse_section_cleanmean (cfg, cpl_cfg);
        parse_section_badpix    (cfg, cpl_cfg);
        parse_section_thresh    (cfg, cpl_cfg); 
        parse_section_qclog     (cfg,cpl_cfg);
      
        parse_section_frames    (cfg, sof, raw,  &status);
        if (status > 0) {
                sinfo_msg_error("parsing cpl input");
                sinfo_flat_cfg_destroy(cfg);
                cfg = NULL ;
                return NULL ;
        }
        return cfg ;
}

/**
  @name     parse_section_frames
  @memo     Parse input frames.
  @param    cfg pointer to flat_config structure
  @param    sof pointer to input set of frames
  @param    raw pointer to input set of raw frames
  @param    status status of function
  @return   void.
*/
static void     
parse_section_frames(flat_config * cfg,
             cpl_frameset * sof,
             cpl_frameset ** raw,
                     int* status)
{
   int                     i;

   char           *       name ;

   int                     nobj, noff ;
   int                     nditherobj, nditheroff ;
   int                     found_sky ;
   int                     found_dither ;
   int nframes=0;
   int nraw=0;
   char* tag;
   char spat_res[FILE_NAME_SZ];
   char lamp_status[FILE_NAME_SZ];
   char band[FILE_NAME_SZ];
   int ins_set=0;

   cpl_frame* frame   = NULL;


   nframes = cpl_frameset_get_size(sof);

   sinfo_extract_raw_frames_type(sof,raw,RAW_FLAT_LAMP);
   nraw=cpl_frameset_get_size(*raw);

   if (nraw==0) {
      sinfo_extract_raw_frames_type(sof,raw,RAW_FLAT_NS);
   }   


   nraw=cpl_frameset_get_size(*raw);
   if (nraw==0) {
       sinfo_msg("Frame %s or %s not found!", RAW_FLAT_LAMP,RAW_FLAT_NS);
       (*status)++;
       return   ;
   }

   nraw  = cpl_frameset_get_size(*raw);

   sinfo_msg("nraw=%d",nraw);
   if(nraw<1) {
     sinfo_msg_error("no good raw frame in input, something wrong!");
     (*status)++;
     return;
   }

   cknull_nomsg(frame = cpl_frameset_get_frame(*raw,0));

   ck0_nomsg(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 \n",
                     spat_res,              lamp_status,    band);

   
   sinfo_get_ins_set(band,&ins_set);


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

   found_sky     = 0 ;
   found_dither  = 0 ;
   nobj          = 0 ;
   noff          = 0 ;
   nditheroff    = 0 ;
   nditherobj    = 0 ;
   for (i=0;i<nraw;i++) {
     cfg->framelist[i]=NULL;
     cfg->frametype[i]=-1;
     cfg->frameposition[i]=-1;
   }


   cfg->nframes         = nraw ;
    /* Browse through the charmatrix to get names and file types */
   for (i=0 ; i<nraw ; i++) {
      frame = cpl_frameset_get_frame(*raw,i);
      name= (char*) cpl_frame_get_filename(frame);
      if(sinfo_file_exists(name)==1) {
    /* to go on the file must exist */
    if(cpl_frame_get_tag(frame) != NULL) {
      /* If the frame has a tag we process it. Else it is an object */ 
      tag= (char*) cpl_frame_get_tag(frame);
          /* sinfo_msg("frame %s tag =%s \n",name,tag); */
          if((sinfo_frame_is_on(frame)  == 0) ||
             (sinfo_frame_is_sky(frame)  == 1) ) 
        {

             cfg->framelist[i]=(char*) cpl_frame_get_filename(frame);
             cfg->frametype[i] = FRAME_OFF ;
             found_sky = 1;
             if (sinfo_frame_is_dither(frame)) 
           {
                cfg->frameposition[i] = FRAME_POS2 ;
                found_dither = 1 ;
                nditheroff++ ;
           }
             else 
           {
                 cfg->frameposition[i] = FRAME_POS1 ;
                 noff++ ;
           }
        }
          else if(sinfo_frame_is_on(frame)  == 1) 
        {
           cfg->framelist[i]=(char*) cpl_frame_get_filename(frame);
           cfg->frametype[i] = FRAME_ON ;
          if (sinfo_frame_is_dither(frame))
        {
          cfg->frameposition[i] = FRAME_POS2 ;
          found_dither = 1 ;
          nditherobj++ ;
        }
              else 
        {
          cfg->frameposition[i] = FRAME_POS1 ;
          nobj++ ;
        }
        }
 
    }
       
        else 
      {
            /* No type means an object */
            /* No type means position 1 */
    /*
        cfg->frametype[i] = FRAME_ON ;
        cfg->frameposition[i] = FRAME_POS1 ;
        nobj ++ ;
    */
      }
      }
      /* Store file name into framelist */
      /* sinfo_msg("frame=%s\n",cfg->framelist[i]); */
    }
   
   /*
   sinfo_msg("Noff= %d Nobj= %d Nditheroff= %d Nditherobj= %d",
                     noff,nobj,nditheroff,nditherobj);
   */


   if((nobj<1) && (nditherobj< 1)) {
     sinfo_msg_error("no ON raw frame in input, something wrong!");
     sinfo_flat_free_alloc(cfg);
     (*status)++;
     return;
   }
 
   /* Copy relevant information into the blackboard */
   cfg->nobj            = nobj ;
   cfg->noff            = noff ;
   cfg->nditherobj      = nditherobj ;
   cfg->nditheroff      = nditheroff ;
   cfg->contains_sky    = found_sky ;
   cfg->contains_dither = found_dither ;

   strcpy(cfg -> outName, LAMP_FLATS_OUT_FILENAME);

   if(cfg->interpolInd != 0) {

      if(NULL != cpl_frameset_find(sof,PRO_BP_MAP)) {
         frame = cpl_frameset_find(sof,PRO_BP_MAP);
         strcpy(cfg -> mask,cpl_frame_get_filename(frame));
         if(sinfo_file_exists(cfg->mask)==1) {
         } else {
            sinfo_msg_error("Filename %s for Frame %s not found!", 
                       cfg->mask, PRO_BP_MAP);
            sinfo_flat_free_alloc(cfg);
            (*status)++;
           return;
 
         }

      } else {
        sinfo_msg_error("Frame %s not found!", PRO_BP_MAP);
        sinfo_flat_free_alloc(cfg);
        (*status)++;
       return;
      } 
      if(NULL != cpl_frameset_find(sof,PRO_SLIT_POS)) {
         frame = cpl_frameset_find(sof,PRO_SLIT_POS);
         strcpy(cfg -> slitposList,cpl_frame_get_filename(frame));
         if(sinfo_file_exists(cfg->mask) == 1) {
         } else {
            sinfo_msg_error("Filename %s for Frame %s not found!", 
                       cfg->slitposList, PRO_SLIT_POS);
            sinfo_flat_free_alloc(cfg);
            (*status)++;
            return;
     }
      } else {
        sinfo_msg_error("Frame %s not found!", PRO_SLIT_POS);
        sinfo_flat_free_alloc(cfg);
        (*status)++;
        return;
      }

   }

  cleanup:

   return;
}

/**
  @name     parse_section_cleanmean
  @memo     Parse cleanmean parameters.
  @param    cfg pointer to flat_config structure
  @param    cpl_cfg pointer to input cpl parameters
  @return   void.
*/
static void     
parse_section_cleanmean(flat_config * cfg, cpl_parameterlist * cpl_cfg)
{
   cpl_parameter *p; 
  
   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.low_rejection");
   cfg -> loReject = cpl_parameter_get_double(p);

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

}

/**
  @name     parse_section_badpixel
  @memo     Parse badpixel parameters.
  @param    cfg pointer to flat_config structure
  @param    cpl_cfg pointer to input cpl parameters
  @return   void.
*/
static void     
parse_section_badpixel(flat_config * cfg, cpl_parameterlist * cpl_cfg)
{
   cpl_parameter *p; 

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.interpol_index");
   cfg -> interpolInd = cpl_parameter_get_bool(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.max_rad");
   cfg -> maxRad =  cpl_parameter_get_int(p);

}

/**
  @name     parse_section_badpix
  @memo     Parse badpix parameters.
  @param    cfg pointer to flat_config structure
  @param    cpl_cfg pointer to input cpl parameters
  @return   void.
*/
static void     
parse_section_badpix(flat_config * cfg, cpl_parameterlist * cpl_cfg)
{

   cpl_parameter* p;

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.bad_ind");
   cfg ->  badInd = cpl_parameter_get_bool(p);

   strcpy(cfg -> maskname, LAMP_FLATS_OUT_BPMAP);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.sigma_factor");
   cfg -> sigmaFactor = cpl_parameter_get_double(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.factor");
   cfg -> factor = cpl_parameter_get_double(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.iterations");
   cfg -> iterations = cpl_parameter_get_int(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.bad_low_rejection");
   cfg -> badLoReject = cpl_parameter_get_double(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.bad_high_rejection");
   cfg -> badHiReject = cpl_parameter_get_double(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.llx");
   cfg -> llx = cpl_parameter_get_int(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.lly");
   cfg -> lly = cpl_parameter_get_int(p);
 
   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.urx");
   cfg -> urx = cpl_parameter_get_int(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.ury");
   cfg -> ury = cpl_parameter_get_int(p);

}

/**
  @name     parse_section_thresh
  @memo     Parse thresh parameters.
  @param    cfg pointer to flat_config structure
  @param    cpl_cfg pointer to input cpl parameters
  @return   void.
*/
static void     
parse_section_thresh(flat_config * cfg,cpl_parameterlist* cpl_cfg)
{

   cpl_parameter* p;
   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.thresh_ind");
   cfg -> threshInd =cpl_parameter_get_bool(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.mean_factor");
   cfg -> meanfactor = cpl_parameter_get_double(p);


}


/**
  @name     parse_section_qclog
  @memo     Parse qclog parameters.
  @param    cfg pointer to flat_config structure
  @param    cpl_cfg pointer to input cpl parameters
  @return   void.
*/
static void     
parse_section_qclog(flat_config * cfg, cpl_parameterlist *   cpl_cfg)
{
   cpl_parameter *p;  

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.qc_fpn_xmin1");
   cfg -> qc_fpn_xmin1 = cpl_parameter_get_int(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.qc_fpn_xmax1");
   cfg -> qc_fpn_xmax1 = cpl_parameter_get_int(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.qc_fpn_ymin1");
   cfg -> qc_fpn_ymin1 = cpl_parameter_get_int(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.qc_fpn_ymax1");
   cfg -> qc_fpn_ymax1 = cpl_parameter_get_int(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.qc_fpn_xmin2");
   cfg -> qc_fpn_xmin2 = cpl_parameter_get_int(p);
   
   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.qc_fpn_xmax2");
   cfg -> qc_fpn_xmax2 = cpl_parameter_get_int(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.qc_fpn_ymin2");
   cfg -> qc_fpn_ymin2 = cpl_parameter_get_int(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.qc_fpn_ymax2");
   cfg -> qc_fpn_ymax2 = cpl_parameter_get_int(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.qc_thresh_min");
   cfg -> qc_thresh_min = cpl_parameter_get_int(p);

   p = cpl_parameterlist_find(cpl_cfg, "sinfoni.lamp_flats.qc_thresh_max");
   cfg -> qc_thresh_max = cpl_parameter_get_int(p);

}
/**
@name sinfo_flat_free
@memo free flat_config structure
@param cfg pointer to flat_config structure
@return void
*/

void
sinfo_flat_free(flat_config ** cfg)
{  
  if ((*cfg) != NULL) {
    sinfo_flat_free_alloc(*cfg);
    sinfo_flat_cfg_destroy(*cfg);
    *cfg=NULL;
  }
  return;

}
/**
@name sinfo_flat_allog
@memo free flat_config structure
@param cfg pointer to flat_config structure
@return void
*/

void 
sinfo_flat_free_alloc(flat_config * cfg)
{
  if(cfg->frametype != NULL){
       cpl_free(cfg->frametype); 
  }
  if(cfg->framelist != NULL) {
     cpl_free(cfg->framelist);
  }
  if(cfg->frameposition != NULL) {
     cpl_free(cfg->frameposition);
  }
return ;
}
