/*                                                                          *
 *   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-01-16 21:09:42 $
 * $Revision: 1.7 $
 */

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

/*-------------------------------------------------------------------------*/
/**
 * @defgroup test_xsh_rectify  Test rectify function
 * @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_data_the_map.h>
#include <xsh_data_localization.h>
#include <xsh_data_spectralformat.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_DETECT_ORDER"

/*--------------------------------------------------------------------------
  Implementation
  --------------------------------------------------------------------------*/
enum {
  SEARCH_WINDOW_HSIZE_OPT, FLUX_THRESH_OPT, MIN_SN_OPT,
  MIN_ORDER_SIZE_X_OPT,  CHUNK_HSIZE_OPT, SLITLET_LOW_FACTOR_OPT,
  SLITLET_UP_FACTOR_OPT, FIXED_SLICE_OPT, METHOD_OPT, HELP_OPT
} ;

static const char * Options = "";

static struct option long_options[] = {
  {"search-window-hsize", required_argument, 0, SEARCH_WINDOW_HSIZE_OPT},
  {"flux-thresh", required_argument, 0, FLUX_THRESH_OPT},
  {"min-sn", required_argument, 0, MIN_SN_OPT},
  {"min-order-size-x", required_argument, 0, MIN_ORDER_SIZE_X_OPT},
  {"chunk-hsize", required_argument, 0, CHUNK_HSIZE_OPT},
  {"slitlet-low-factor", required_argument, 0, SLITLET_LOW_FACTOR_OPT},
  {"slitlet-up-factor",required_argument, 0, SLITLET_UP_FACTOR_OPT},
  {"fixed-slice",required_argument, 0, FIXED_SLICE_OPT},
  {"method",required_argument, 0, METHOD_OPT},
  {"help", 0, 0, HELP_OPT},
  {0, 0, 0, 0}
};

static void Help( void )
{
  puts( "Unitary test of xsh_detect_order" ) ;
  puts( "Usage: test_xsh_detect_order [options] <input_files>" ) ;
  puts( "Options" ) ;
  puts( " --search-window-hsize=<n>    : Half size of the search box" ) ;
  puts( " --flux-thresh=<nn>           : Threshold in flux" ) ;
  puts( " --min-sn=<n>                 : Minimum s/n ratio" ) ;
  puts( " --min-order-size-x=<n>       : Minimum pixel size of an order in cross dispersion" ) ;
  puts( " --chunk-hsize=<n>    : Pixel half size of chunk of an order in dispersion" );
  puts( " --slitlet-low-factor=<n>     : ????" );
  puts( " --slitlet-up-factor=<n>      : ????" );
  puts( " --fixed-slice=<n>            : if TRUE used slitlet ratio" );
  puts( " --method=<n>                 : ????" );
  puts( " --help             : What you see" ) ;
  puts( "\nInput Files" ) ;
  puts( "The input files argument MUST be in this order:" ) ;
  puts( " 1. Science frame FLAT" ) ;
  puts( " 2. SOF (ORDER_TAB_CEN]\n" ) ;
  TEST_END();
}

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

  while (( opt = getopt_long (argc, argv, Options,
                              long_options, &option_index)) != EOF )
    switch ( opt ) {
    case SEARCH_WINDOW_HSIZE_OPT:
      detectorder_par->search_window_hsize = atoi( optarg);
      break ;
    case FLUX_THRESH_OPT:
      detectorder_par->flux_thresh = atof( optarg);
      break ;
    case MIN_SN_OPT:
      detectorder_par->min_sn = atof( optarg);
      break ;
    case MIN_ORDER_SIZE_X_OPT:
      detectorder_par->min_order_size_x = atoi( optarg);
      break ;
    case CHUNK_HSIZE_OPT:
      detectorder_par->chunk_hsize = atoi( optarg);
      break;
    case SLITLET_LOW_FACTOR_OPT:
      detectorder_par->slitlet_low_factor = atof( optarg);
      break;
    case SLITLET_UP_FACTOR_OPT:
      detectorder_par->slitlet_up_factor = atof( optarg);
      break ;
    case FIXED_SLICE_OPT:
      detectorder_par->fixed_slice = atoi( optarg);      
      break ;
    case METHOD_OPT:
      detectorder_par->method = optarg;
      break;
    default: Help() ; exit( 0);
    }
}

/**
  @brief
    Unit test of xsh_rectify. Needs the PRE frame, order table, wave solution,
        instrument, rectify parameters, the map.
  @return
    0 if success

*/
int main( int argc, char **argv)
{
  /* Declarations */
  int ret = 0 ;

  xsh_instrument* instrument = NULL;

  const char *sof_name = NULL;
  cpl_frameset *set = NULL;

  const char * sci_name = NULL ;

  cpl_frame *sci_frame = NULL;
  cpl_frame *orderlist_frame = NULL;
  cpl_frame *edges_order_tab_frame = NULL;
  xsh_detect_order_param detectorder_par;
  const int decode_bp=2147483647;
  /* Initialize libraries */
  TESTS_INIT(MODULE_ID);
  cpl_msg_set_level(CPL_MSG_DEBUG);
  xsh_debug_level_set(XSH_DEBUG_LEVEL_MEDIUM);

  /* Set detectorder default params */
  detectorder_par.search_window_hsize = 50;
  detectorder_par.flux_thresh = 0.05;
  detectorder_par.min_sn = 35.;
  detectorder_par.min_order_size_x = 60;
  detectorder_par.chunk_hsize = 1;
  detectorder_par.slitlet_low_factor = 1.0;
  detectorder_par.slitlet_up_factor = 1.0;
  detectorder_par.fixed_slice = CPL_TRUE;
  detectorder_par.method = "fixed";

  HandleOptions( argc, argv, &detectorder_par);

  if ( (argc - optind) >=2 ) {
    sci_name = argv[optind];
    sof_name = argv[optind+1];
  }
  else {
    Help();
    exit(0);
  }
  /* Create frameset from sof */
  check( set = sof_to_frameset( sof_name));
  /* Validate frame set */
  check( instrument = xsh_dfs_set_groups( set));
  xsh_instrument_set_decode_bp( instrument, decode_bp ) ;
  check( orderlist_frame = xsh_find_order_tab_centr( set, instrument));

  TESTS_XSH_FRAME_CREATE( sci_frame, "FLAT_arm", sci_name);

  xsh_msg("SCI            : %s",
    cpl_frame_get_filename( sci_frame));
  xsh_msg("ORDERLIST      : %s",
    cpl_frame_get_filename( orderlist_frame));

  xsh_msg(" Parameters ");
  xsh_msg(" search window half size %d", detectorder_par.search_window_hsize);
  xsh_msg(" flux threshold %f", detectorder_par.flux_thresh);
  xsh_msg(" min S/N %f", detectorder_par.min_sn);
  xsh_msg(" min order size cross dispersion %d", detectorder_par.min_order_size_x);
  xsh_msg(" chunk hsize %d", detectorder_par.chunk_hsize);
  xsh_msg(" slitlet low factor %f", detectorder_par.slitlet_low_factor);
  xsh_msg(" slitlet up factor %f", detectorder_par.slitlet_up_factor);
  xsh_msg(" fixed slice %d", detectorder_par.fixed_slice);
  xsh_msg(" detect method %s",detectorder_par.method);

  /* Now detect_order the frame */
  check( edges_order_tab_frame = xsh_detect_order_edge( sci_frame,
    orderlist_frame, &detectorder_par, instrument));

  cleanup:
     if (cpl_error_get_code() != CPL_ERROR_NONE) {
      xsh_error_dump(CPL_MSG_ERROR);
      ret = 1;
    }
    xsh_free_frame( &sci_frame);
    xsh_free_frame( &edges_order_tab_frame);
    xsh_free_frameset( &set);
    xsh_instrument_free( &instrument);
    TEST_END();
    return ret;
}
/**@}*/


