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