/*
 * 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_ns_ini_by_cpl.c
   Author       :   Andrea Modigliani
   Created on   :   May 19, 2003
   Description  :   cpl input handling for the north-south test

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

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


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

#include <string.h>
#include "sinfo_ns_ini_by_cpl.h"
#include "sinfo_pro_types.h"
#include "sinfo_hidden.h"
#include "sinfo_functions.h"
#include "sinfo_file_handling.h"

/*---------------------------------------------------------------------------
                    Functions private to this module
 ---------------------------------------------------------------------------*/
void sinfo_ns_free_alloc(ns_config * cfg);
static void     
parse_section_frames (ns_config *,cpl_parameterlist* cpl_cfg,cpl_frameset* sof,
                      cpl_frameset** raw, int* status);
static void     
parse_section_cleanmean (ns_config *,cpl_parameterlist* cpl_cfg);
static void     
parse_section_gaussconvolution (ns_config *,cpl_parameterlist* cpl_cfg);
static void     
parse_section_northsouthtest(ns_config *,cpl_parameterlist* cpl_cfg);


/**@{*/
/**
 * @addtogroup sinfo_rec_distortion North South Test initialization
 *
 * TBD
 */



/* removed generateNS_ini_file */

/*-------------------------------------------------------------------------*/
/**
  @name     parse_ns_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 ns_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.
 */
/*--------------------------------------------------------------------------*/

ns_config * 
sinfo_parse_cpl_input_ns(cpl_parameterlist * cpl_cfg, cpl_frameset* sof, 
                         cpl_frameset** raw)
{
    ns_config   *         cfg = sinfo_ns_cfg_create();
    int status=0;
    /*
     * Perform sanity checks, fill up the structure with what was
     * found in the ini file
     */

    parse_section_cleanmean        (cfg,cpl_cfg);
    parse_section_gaussconvolution (cfg,cpl_cfg);
    parse_section_northsouthtest   (cfg,cpl_cfg);
    parse_section_frames           (cfg,cpl_cfg,sof,raw,&status);

    if (status > 0) {
        sinfo_msg_error("parsing cpl input");
        sinfo_ns_cfg_destroy(cfg);
        cfg = NULL ;
        return NULL ;
    }
    return cfg ;
}




static void     
parse_section_frames(ns_config * cfg,
                     cpl_parameterlist * cpl_cfg,
                     cpl_frameset * sof,
                     cpl_frameset ** raw,
                     int* status)
{
    int                     i;
    int                     nobj ;
    int                     noff ;
    int nraw=0;
    char* tag;
    cpl_frame* frame   = NULL;
    cpl_parameter *p;
    char spat_res[FILE_NAME_SZ];
    char lamp_status[FILE_NAME_SZ];
    char band[FILE_NAME_SZ];
    int ins_set=0;
    nstpar* nstp=sinfo_nstpar_new();

    sinfo_extract_raw_frames_type(sof,raw,PRO_FIBRE_NS_STACKED_DIST);

    nraw    = cpl_frameset_get_size(*raw);

    if(nraw == 0) {
        sinfo_msg_error("No input raw frames");
        sinfo_nstpar_delete(nstp);
        (*status)++;
        return;
    }

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



    /* Browse through the charmatrix to get names and file types */
    i=0 ;
    nobj = 0 ;
    noff = 0 ;

    for (i=0 ; i<nraw ; i++) {
        frame = cpl_frameset_get_frame(*raw,i);
        if(sinfo_file_exists((char*) cpl_frame_get_filename(frame))==1)
        {
            /* to go on the file must exist */
            tag=(char*) cpl_frame_get_tag(frame);
            if(cpl_frame_get_tag(frame) != NULL) {
                /* If the frame has a tag we process it. Else it is an object */
                if((sinfo_frame_is_on(frame)  == 0))
                {
                    cfg->framelist[i]=(char*) cpl_frame_get_filename(frame);
                    cfg->frametype[i] = FRAME_OFF ;
                    noff++;
                }
                else if(sinfo_is_sky_flat(tag))
                {
                    cfg->framelist[i]=(char*) cpl_frame_get_filename(frame);
                    cfg->frametype[i] = FRAME_OFF ;
                    noff++;
                }
                else if((sinfo_frame_is_on(frame)  == 1))
                {
                    cfg->framelist[i]=(char*) cpl_frame_get_filename(frame);
                    cfg->frametype[i] = FRAME_ON ;
                    nobj++;
                }
                else
                {
                    /* without label the frame is assumed on */
                    cfg->framelist[i]=(char*) cpl_frame_get_filename(frame);
                    cfg->frametype[i] = FRAME_ON ;
                    nobj++;
                }
            }
            else
            {
                /* without label the frame is assumed on */
                cfg->framelist[i]=(char*) cpl_frame_get_filename(frame);
                cfg->frametype[i] = FRAME_ON ;
                nobj++;
            }
            /* Store file name into framelist */
        }
        else {
            sinfo_msg_warning("file %s does not exist",
                            cpl_frame_get_filename(frame));
        }

    }


    if((noff == 0) && (nobj == 0)) {
        sinfo_msg_error("Wrong input frames");
        sinfo_nstpar_delete(nstp);
        sinfo_ns_free_alloc(cfg);
        (*status)++;
        return;
    }
    /* Copy relevant information into the blackboard */
    cfg->nframes         = nraw ;
    cfg->nobj            = nobj ;
    cfg->noff            = noff ;

    strcpy(cfg -> outName, NS_TEST_DISTANCES_OUT_FILENAME);


    frame = cpl_frameset_get_frame(*raw,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 \n",
              spat_res,    lamp_status,    band);


    sinfo_get_ins_set(band,&ins_set);


    p = cpl_parameterlist_find(cpl_cfg, "sinfoni.north_south_test.fwhm");
    if(cpl_parameter_get_double(p) != cpl_parameter_get_default_double(p)) {
        cfg -> fwhm = cpl_parameter_get_double(p);
    } else {
        cfg -> fwhm = nstp->fwhm[ins_set];
    }

    p = cpl_parameterlist_find(cpl_cfg, "sinfoni.north_south_test.min_diff");
    if(cpl_parameter_get_double(p) != cpl_parameter_get_default_double(p)) {
        cfg -> minDiff = cpl_parameter_get_double(p);
    } else {
        cfg -> minDiff = nstp->min_dif[ins_set];
    }
    sinfo_nstpar_delete(nstp);


    if(cfg -> maskInd) {
        if(NULL != cpl_frameset_find(sof,PRO_BP_MAP_DI)) {
            frame = cpl_frameset_find(sof,PRO_BP_MAP_DI);
            strcpy(cfg -> mask,cpl_frame_get_filename(frame));
        } else {
            sinfo_msg_error("Frame %s not found! Exit!", PRO_BP_MAP_DI);
            sinfo_ns_free_alloc(cfg);
            (*status)++;
            return;
        }
    }


    return ;
}

static void     
parse_section_cleanmean(ns_config * cfg,cpl_parameterlist * cpl_cfg)
{

    cpl_parameter *p;
    p = cpl_parameterlist_find(cpl_cfg,
                    "sinfoni.north_south_test.low_rejection");
    cfg -> loReject = cpl_parameter_get_double(p);

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

    p = cpl_parameterlist_find(cpl_cfg, "sinfoni.north_south_test.mask_ind");
    cfg -> maskInd = cpl_parameter_get_bool(p);

    return ;
}

static void     
parse_section_gaussconvolution(ns_config * cfg,cpl_parameterlist * cpl_cfg)
{
    cpl_parameter *p;
    p = cpl_parameterlist_find(cpl_cfg, "sinfoni.north_south_test.gauss_ind");
    cfg -> gaussInd = cpl_parameter_get_bool(p);

    p = cpl_parameterlist_find(cpl_cfg,
                    "sinfoni.north_south_test.kernel_half_width");
    cfg -> hw = cpl_parameter_get_int(p);

}

static void     
parse_section_northsouthtest(ns_config  * cfg,cpl_parameterlist * cpl_cfg)
{

    cpl_parameter *p;
    strcat(cfg -> fitsname, NS_TEST_OUT_FILENAME);
    cfg -> nslits = NSLITLETS;

    p = cpl_parameterlist_find(cpl_cfg, "sinfoni.north_south_test.half_width");
    cfg -> halfWidth = cpl_parameter_get_int(p);

    p = cpl_parameterlist_find(cpl_cfg, "sinfoni.north_south_test.fwhm");
    cfg -> fwhm = cpl_parameter_get_double(p);

    p = cpl_parameterlist_find(cpl_cfg, "sinfoni.north_south_test.min_diff");
    cfg -> minDiff = cpl_parameter_get_double(p);

    cfg -> estimated_dist = ESTIMATED_SLITLETS_DISTANCE;

    p = cpl_parameterlist_find(cpl_cfg, "sinfoni.north_south_test.dev_tol");
    cfg -> devtol = cpl_parameter_get_double(p);

    return ;
}

void
sinfo_ns_free(ns_config ** cfg)
{  
    if(*cfg!=NULL) {
        sinfo_ns_free_alloc(*cfg);
        sinfo_ns_cfg_destroy(*cfg);
        *cfg=NULL;
    }
    return;

}
void
sinfo_ns_free_alloc(ns_config * cfg)
{
    if(cfg->framelist != NULL) {
        cpl_free(cfg->framelist);
        cfg->framelist=NULL;
    }
    if(cfg->frametype != NULL) {
        cpl_free(cfg->frametype);
        cfg->frametype=NULL;
    }

    return;

}
/**@}*/
