/*                                                                          *
 *   This file is part of the ESO X-shooter Pipeline                        *
 *   Copyright (C) 2006 European Southern Observatory                       *
 *                                                                          *
 *   This library 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   *
 *                                                                          */
 
/*
 * $Author: amodigli $
 * $Date: 2012-11-16 16:27:02 $
 * $Revision: 1.23 $
 */

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

/*-------------------------------------------------------------------------*/
/**
 * @defgroup test_xsh_remove_crh_single  Test Remove Crh Multi function(s)
 * @ingroup unit_tests
 * 
 */
/*-------------------------------------------------------------------------*/
/**@{*/

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

#include <tests.h>

#include <xsh_data_pre.h>
#include <xsh_error.h>
#include <xsh_msg.h>
#include <xsh_data_instrument.h>
#include <xsh_drl.h>
#include <xsh_pfits.h>

#include <xsh_badpixelmap.h>

#include <cpl.h>
#include <math.h>

#include <getopt.h>

/*--------------------------------------------------------------------------
  Defines
  --------------------------------------------------------------------------*/

#define MODULE_ID "XSH_REMOVE_CRH_SINGLE"

static void Help( void)
{
  puts( "Unitary test of xsh_remove_crh_single");
  puts( "Usage: test_xsh_remove_crh_single [options] <input_files>");

  puts( "Options" ) ;
  puts( " --sigma_lim=<n>    : Sigma limit (5.0]" ) ;
  puts( " --f_lim=<n>        : F limit [2.0]" ) ;
  puts( " --iter=<n>         : Number of iteration [4]" ) ;
  puts( " --frac_max=<n>     : Maximum rejected fraction [0.1]");
  puts( " --debug=<n>        : Level of debug LOW | MEDIUM | HIGH [MEDIUM]" );
  puts( " --help             : What you see" ) ;
  puts( "\nInput Files" ) ;
  puts( "The input files argument MUST be in this order:" ) ;
  puts( " 1. Science frame in PRE format sky subtracted" ) ;
  puts( " 2. SOF [WAVE_MAP]\n" ) ;
  TESTS_CLEAN_WORKSPACE(MODULE_ID);
  TEST_END();
}

enum {
  SIGMA_LIM_OPT,
  F_LIM_OPT,
  ITER_OPT,
  FRAC_MAX_OPT,
  DEBUG_OPT,
  HELP_OPT
} ;

static struct option long_options[] = {
  {"sigma_lim", required_argument, 0, SIGMA_LIM_OPT}, 
  {"f_lim", required_argument, 0, F_LIM_OPT},
  {"iter", required_argument, 0, ITER_OPT},
  {"frac_max", required_argument, 0, FRAC_MAX_OPT},
  {"debug", required_argument, 0, DEBUG_OPT}, 
  {"help", 0, 0,HELP_OPT},
 {0, 0, 0, 0}
};

static void HandleOptions( int argc, char **argv,
			   xsh_remove_crh_single_param *single_par)
{
  int opt ;
  int option_index = 0;

  while (( opt = getopt_long (argc, argv, "sigma_lim:f_lim",
    long_options, &option_index)) != EOF ){
    switch ( opt ) {
    case  SIGMA_LIM_OPT:
      single_par->sigma_lim = atof(optarg);
      break ;
    case  F_LIM_OPT:
      single_par->f_lim = atof(optarg);
      break ;
    case FRAC_MAX_OPT:
      single_par->crh_frac_max = atof(optarg);
      break;
    case ITER_OPT:
      sscanf( optarg, "%64d", &single_par->nb_iter ) ;
      break ;
    case DEBUG_OPT:
      if ( strcmp( optarg, "LOW")==0){
        xsh_debug_level_set( XSH_DEBUG_LEVEL_LOW);
      }
      else if ( strcmp( optarg, "HIGH")==0){
        xsh_debug_level_set( XSH_DEBUG_LEVEL_HIGH);
      }
      break;
    default:
      Help();
      exit(-1);
    }
  }
  return;
}

/*--------------------------------------------------------------------------
  Implementation
  --------------------------------------------------------------------------*/

/**
  @brief
    Unit test of xsh_remove_crh_single
  @return
    0 if success

   Test behaviour of xsh_remove_crh_single function.
*/
int main( int argc, char **argv)
{
  /* Declarations */
  int ret = 0 ;
  char name[256];
  char sof_name[256];
  char res_name[64] ;

  cpl_frameset* raw = NULL;
  cpl_frameset *set = NULL;
  cpl_frame* sciraw_frame = NULL;
  cpl_frame* sci_frame = NULL;
  cpl_frame* wavemap_frame = NULL;
  cpl_frame* frame_rmcrh = NULL;
  xsh_instrument* instrument = NULL;
  xsh_remove_crh_single_param single_par = { 0.1,2.5,2.0, 4 } ;
  XSH_INSTRCONFIG* iconfig = NULL;
  cpl_image* test_image = NULL;
  cpl_propertylist * header = NULL ;

  /* Initialize libraries */
  TESTS_INIT_WORKSPACE(MODULE_ID);
  TESTS_INIT(MODULE_ID);
  cpl_msg_set_level( CPL_MSG_DEBUG);
  xsh_debug_level_set( XSH_DEBUG_LEVEL_MEDIUM) ;


  /* Analyse parameters */
  single_par.sigma_lim = 5.0;
  single_par.f_lim = 2.0;
  single_par.nb_iter = 4;

  HandleOptions( argc, argv, &single_par);

  if (argc-optind > 1){
    sprintf(name, argv[optind]);
    sprintf( sof_name, argv[optind+1]);

    TESTS_XSH_FRAME_CREATE( sci_frame, "OBJECT_SLIT_STARE_arm", name);
    /* Create frameset from sof */
    check( set = sof_to_frameset( sof_name));

    /* Validate frame set */
    check( instrument = xsh_dfs_set_groups( set));
    check( wavemap_frame = xsh_find_wavemap( set, instrument));
  }
  else{
    xsh_msg("-------------------------------------------");
    xsh_msg("Execute default test : do --help for option");
    xsh_msg("-------------------------------------------");

    instrument = xsh_instrument_new() ;
    xsh_instrument_set_mode( instrument, XSH_MODE_IFU ) ;
    xsh_instrument_set_arm( instrument, XSH_ARM_UVB) ;
    xsh_instrument_set_lamp( instrument, XSH_LAMP_QTH ) ;
    iconfig = xsh_instrument_get_config( instrument ) ;

  /* Generate tests data */
    test_image = cpl_image_fill_test_create(10,10);
    sprintf(name, "remove_crh_single_sci_UVB.fits");
    header = mkHeader( iconfig, 10, 10, 1.) ; 
    cpl_image_save(test_image, name, CPL_BPP_IEEE_DOUBLE, header,
      CPL_IO_DEFAULT);
    sciraw_frame = cpl_frame_new();
    cpl_frame_set_filename( sciraw_frame, name) ;
    cpl_frame_set_tag( sciraw_frame, "BIAS_UVB");
    cpl_frame_set_level( sciraw_frame, CPL_FRAME_LEVEL_TEMPORARY);
    cpl_frame_set_group( sciraw_frame, CPL_FRAME_GROUP_RAW);

    raw = cpl_frameset_new();
    check( cpl_frameset_insert( raw, sciraw_frame));
 
    check( xsh_prepare( raw, NULL, NULL, "BIAS_UVB", instrument,0,CPL_FALSE));
    check( sci_frame = cpl_frame_duplicate( cpl_frameset_get_first( raw)));
  }

  xsh_msg("---Input Frames");
  xsh_msg("sky subtracted frame : %s", name);
  if ( wavemap_frame != NULL){
    xsh_msg("Wave map frame : %s", cpl_frame_get_filename( wavemap_frame));
  }

  xsh_msg("---Parameters");
  xsh_msg("  frac max  : %f", single_par.crh_frac_max);
  xsh_msg("  sigma_lim : %f", single_par.sigma_lim);
  xsh_msg("  f_lim     : %f", single_par.f_lim);
  xsh_msg("  niter     : %d", single_par.nb_iter);
  
  /* Call xsh_remove_crh_single */
  sprintf( res_name, "NOCRH_%s.fits", 
    xsh_instrument_arm_tostring( instrument));


  xsh_instrument_set_recipe_id( instrument, "xsh_mdark" ) ;

  check(frame_rmcrh = xsh_remove_crh_single( sci_frame,
    instrument, NULL,&single_par, res_name));


  cleanup:
    xsh_instrument_free( &instrument);
    xsh_free_frameset( &raw);
    xsh_free_frameset( &set);
    xsh_free_propertylist( &header);
    xsh_free_image ( &test_image);
    xsh_free_frame( &frame_rmcrh);
    xsh_free_frame( &sci_frame);

    if (cpl_error_get_code() != CPL_ERROR_NONE) {
      xsh_error_dump(CPL_MSG_ERROR);
      ret=1;
    }
    TESTS_CLEAN_WORKSPACE(MODULE_ID);
    TEST_END();
    return ret ;
}
/**@}*/
