/*                                                                          *
 *   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_localize_ifu
 * @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_spectrum.h>
#include <xsh_data_localization.h>
#include <xsh_drl.h>
#include <xsh_pfits.h>
#include <xsh_parameters.h>
#include <xsh_badpixelmap.h>
#include <xsh_utils_ifu.h>
#include <xsh_utils_table.h>
#include <cpl.h>
#include <math.h>

#include <string.h>
#include <getopt.h>

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

#define MODULE_ID "XSH_LOCALIZE_IFU"

enum {
  SMOOTH_HSIZE_OPT, NSCALES_OPT, HF_SKIP_OPT, SIGMA_LOW_OPT, SIGMA_UP_OPT,
  SNR_LOW_OPT,SNR_UP_OPT,
  BOX_HSIZE_OPT, 
  SLIT_MIN_OPT, SLIT_MAX_OPT, DEG_OPT, SKYMASK_OPT, HELP_OPT
} ;

static struct option long_options[] = {
  {"smooth-hsize", required_argument, 0,  SMOOTH_HSIZE_OPT},
  {"nscales", required_argument, 0,  NSCALES_OPT},
  {"HF-skip", required_argument, 0,  HF_SKIP_OPT},
  {"cut-sigma-low", required_argument, 0,  SIGMA_LOW_OPT},
  {"cut-sigma-up", required_argument, 0,  SIGMA_UP_OPT},
  {"cut-snr-low", required_argument, 0,  SNR_LOW_OPT},
  {"cut-snr-up", required_argument, 0,  SNR_UP_OPT},
  {"box-hsize", required_argument, 0,  BOX_HSIZE_OPT},
  {"slit-min", required_argument, 0,  SLIT_MIN_OPT},
  {"slit-max", required_argument, 0,  SLIT_MAX_OPT},
  {"deg", required_argument, 0,  DEG_OPT},
  {"skymask", required_argument, 0,  SKYMASK_OPT},
  {"help", 0, 0, HELP_OPT},
  {0, 0, 0, 0}
};

static void Help( void )
{
  puts( "Unitary test of xsh_localize_ifu");
  puts( "Usage: test_xsh_localize_ifu [options] DATA_FILE");

  puts( "Options" ) ;
  puts( " --help             : What you see" ) ;
  puts( " --smooth-hsize=    : Half size of median smooth filter");
  puts( " --nscales=         : Number of scales");
  puts( " --HF-skip=         : Number of skipping High Frequency");
  puts( " --cut-sigma-low=   : Gaussian fits of the cross-dispersion profile whose FWHM is lower than this value are rejected.[0.05]");
  puts( " --cut-sigma-up =   : Gaussian fits of the cross-dispersion profile whose FWHM is upper than this value are rejected.[0.95]");
  puts( " --cut-snr-low=     : Gaussian fits of the cross-dispersion profile whose SNR is lower than this value are rejected.[0.05]");
  puts( " --cut-snr-up=      : Gaussian fits of the cross-dispersion profile whose SNR is upper than this value are rejected.0.95]");
  puts( " --box-hsize=       : Half size of running chunk box");
  puts( " --slit-min=        : Maximum slit in arcsec [-6.0]");
  puts( " --slit-max=        : Minimum slit in arcsec [6.0]");
  puts( " --deg     =        : Minimum slit in arcsec [2]");
  puts( " --skymask=<file>   : Sky mask file");
  puts( "\nInput Files" ) ;
  puts( "DATA_FILE           : Merge 2D frame");
  TEST_END();
}


static void HandleOptions( int argc, char **argv, 
  int *smooth_hsize, int *nscales, int *HF_skip, 
  double *sigma_low, double *sigma_up, double *snr_low, double *snr_up,
  int *box_hsize, double *slitmin, double *slitmax, int *deg, char **skymask_name)
{
  int opt ;
  int option_index = 0;

  while (( opt = getopt_long (argc, argv, 
    "cut-sigma:smooth-hsize:nscales:HF-skip:deg",
    long_options, &option_index)) != EOF ){
  
    switch ( opt ) {
    case  SMOOTH_HSIZE_OPT:
      *smooth_hsize = atoi(optarg);
      break; 
    case  NSCALES_OPT:
      *nscales = atoi(optarg);
      break ; 
    case  HF_SKIP_OPT:
      *HF_skip = atoi(optarg);
      break ;
    case SIGMA_LOW_OPT:
      *sigma_low = atof( optarg);
      break;
    case SIGMA_UP_OPT:
      *sigma_up = atof( optarg);
      break;
    case SNR_LOW_OPT:
      *snr_low = atof( optarg);
      break;
    case SNR_UP_OPT:
      *snr_up = atof( optarg);
      break;
    case BOX_HSIZE_OPT:
      *box_hsize = atoi( optarg);
      break;
    case SLIT_MIN_OPT:
      *slitmin = atof( optarg);
      break;
    case SLIT_MAX_OPT:
      *slitmax = atof( optarg);
      break;
    case DEG_OPT:
      *deg = atoi( optarg);
      break;
    case SKYMASK_OPT:
      *skymask_name = optarg;
      break;
    default: 
      Help(); exit(-1);
    }
  }
  return;
}


int main( int argc, char **argv)
{
  /* Declarations */
  int ret = 0 ;
  int nscales = 5;
  int HF_skip = 2;
  int smooth_hsize = 2;

  const char *file_name = NULL;
  cpl_frame *merge2d_frame = NULL;
  cpl_frame *result = NULL;
  char result_name[256];
  int i;
  cpl_table *result_tab = NULL;
  int result_size;
  double *wave_result_data = NULL;
  double *slit_result_data = NULL;
  FILE *result_file = NULL;

  double sigma_low = 0.05;
  double sigma_up = 0.95;
  double snr_low = 0.05;
  double snr_up = 0.95;

  int box_hsize = 0;
  double slitmin =-6;
  double slitmax = 6;

  int deg =2;

  char * skymask_name = NULL;
  cpl_frame *skymask_frame = NULL;
  
  cpl_propertylist *plist = NULL;
  XSH_ARM arm = XSH_ARM_UNDEFINED;
  xsh_instrument* instrument = NULL;
  const char* tag = NULL;


  //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);

  /* Analyse parameters */
  HandleOptions( argc, argv, &smooth_hsize, &nscales, &HF_skip, 
    &sigma_low, &sigma_up, &snr_low, &snr_up,
    &box_hsize, &slitmin, &slitmax, &deg, &skymask_name);

  if ( (argc - optind) > 0 ) {
    file_name = argv[optind];
  }
  else {
    Help();
    exit( 0);
  }
  
  check( plist = cpl_propertylist_load( file_name, 0));
  check( arm = xsh_pfits_get_arm( plist));
  TESTS_XSH_INSTRUMENT_CREATE( instrument, XSH_MODE_IFU, arm,
    XSH_LAMP_UNDEFINED, "xsh_geom_ifu");
  
  xsh_msg("---Input Files");
  xsh_msg("File    : %s ", file_name);
  xsh_msg("---Options");
  xsh_msg("SMOOTH_HSIZE : %d ", smooth_hsize);
  xsh_msg("NSCALES : %d ", nscales);
  xsh_msg("HF_SKIP : %d ", HF_skip);
  xsh_msg("SIGMA   : [%f %f]", sigma_low, sigma_up);
  xsh_msg("SNR     : [%f %f]", snr_low, snr_up);
  xsh_msg("BOX HSIZE: %d", box_hsize);
  xsh_msg("SLIT MIN:  %f", slitmin);
  xsh_msg("SLIT MAX:  %f", slitmax);
  xsh_msg("DEG    :   %d", deg);
  if ( skymask_name){
    xsh_msg("SKYMASK    :   %s", skymask_name);
    tag = XSH_GET_TAG_FROM_ARM( XSH_SKY_LINE_LIST, instrument);
    TESTS_XSH_FRAME_CREATE( skymask_frame, tag, skymask_name);  
  }
  /* Create frames */
  tag = XSH_GET_TAG_FROM_ARM( XSH_MERGE2D, instrument);
  TESTS_XSH_FRAME_CREATE( merge2d_frame, tag, file_name);

  if ( strstr( file_name, "CEN") != NULL){
    sprintf( result_name, "decomp_CEN.fits");
  }
  else if ( strstr( file_name, "UP") != NULL){
    sprintf( result_name, "decomp_UP.fits");
  }
  else if ( strstr( file_name, "DOWN") != NULL){
    sprintf( result_name, "decomp_DOWN.fits");
  }
  else{
    sprintf( result_name, "decomp.fits");
  }

  check( result = xsh_localize_ifu_slitlet( merge2d_frame, 
    skymask_frame, smooth_hsize, nscales, 
    HF_skip, result_name, sigma_low, sigma_up,
    snr_low, snr_up, slitmin, slitmax, deg, box_hsize, instrument));

  xsh_msg( "Produce file %s", result_name);

  XSH_TABLE_LOAD( result_tab, result_name);
  check( wave_result_data = cpl_table_get_data_double( result_tab,
      XSH_OBJPOS_COLNAME_WAVELENGTH));
  check( slit_result_data = cpl_table_get_data_double( result_tab,
      XSH_OBJPOS_COLNAME_SLIT));
  result_size = cpl_table_get_nrow( result_tab); 

  result_file = fopen("LOCALIZE_IFU.reg", "w+");

  fprintf( result_file, "# Region file format: DS9 version 4.0\n");

  fprintf( result_file, "#yellow center\n");
  fprintf( result_file, "global color=red font=\"helvetica 4 normal\"select=1 highlite=1 edit=1 move=1 delete=1 include=1 fixed=0 source=1\n");
  fprintf( result_file, "wcs\n");

  for( i=0; i< result_size; i++){
    double wave, slit;

    wave = wave_result_data[i];
    slit = slit_result_data[i];

    fprintf( result_file, "point(%f,%f)\n #point=cross color=yellow font=\"helvetica 4 normal\"\n", wave, slit);
  }

  fclose( result_file);  

  xsh_msg( "Produce ds9 region file LOCALIZE_IFU.reg");
  cleanup:
    if (cpl_error_get_code() != CPL_ERROR_NONE) {
      xsh_error_dump(CPL_MSG_ERROR);
      ret=1;
    }
    xsh_free_frame( &skymask_frame);
    xsh_instrument_free( &instrument);
    xsh_free_propertylist( &plist);    
    xsh_free_frame( &result);
    xsh_free_frame( &merge2d_frame);
    XSH_TABLE_FREE( result_tab);
    TEST_END();
    return ret ;
}

/**@}*/
