/*                                                                          *
 *   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: 2013-05-14 07:02:49 $
 * $Revision: 1.3 $
 */

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

/*-------------------------------------------------------------------------*/
/**
 * @defgroup test_xsh_extract_clean  Test Object extraction with bad pixels interpolation
 * @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_rec.h>
#include <xsh_data_localization.h>
#include <xsh_drl.h>
#include <xsh_pfits.h>

#include <xsh_badpixelmap.h>
#include <xsh_parameters.h>

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

#include <getopt.h>

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

#define MODULE_ID "XSH_EXTRACT_CLEAN"

enum {
  DECODEBP_OPT,METHOD_OPT,DEBUG_OPT,HELP_OPT
} ;

static struct option long_options[] = {
  {"decode-bp", required_argument, 0, DECODEBP_OPT},
  {"method", required_argument, 0, METHOD_OPT},
  {"debug", required_argument, 0, DEBUG_OPT},
  {"help", 0, 0, HELP_OPT},
  {0, 0, 0, 0}
};

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

  puts( "Options" ) ;
  puts( " --decode-bp=<n>    : Integer representation of the bits to be considered bad when decoding the bad pixel mask pixel values."); 
  puts( " --method=<n>       : method for extraction CLEAN | LOCALIZATION | FULL | NOD"); 
  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. Rectified frame 2D" ) ;
  puts( " 2. Localization table");
  TEST_END();
  exit(0);
}

static void HandleOptions( int argc, char **argv,
			   xsh_extract_param *extract_par,int* decode_bp)
{
  int opt ;
  int option_index = 0;

  while (( opt = getopt_long (argc, argv, "slit_position:slit_height:method",
    long_options, &option_index)) != EOF ){

    switch ( opt ) {
    case  METHOD_OPT:
      if ( strcmp(optarg, EXTRACT_METHOD_PRINT( LOCALIZATION_METHOD)) == 0){
        extract_par->method = LOCALIZATION_METHOD;
      }
      else if ( strcmp(optarg, EXTRACT_METHOD_PRINT( FULL_METHOD)) == 0){
        extract_par->method = FULL_METHOD;
      }
      else if ( strcmp(optarg, EXTRACT_METHOD_PRINT( CLEAN_METHOD)) == 0){
        extract_par->method = CLEAN_METHOD;
      }
      else if ( strcmp(optarg, EXTRACT_METHOD_PRINT( NOD_METHOD)) == 0){
        extract_par->method = NOD_METHOD;
      }
      else{
        xsh_msg("WRONG method %s", optarg);
        exit(-1);
      }
      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;
    case DECODEBP_OPT:
      *decode_bp=atoi(optarg);
      break;

    case HELP_OPT:
      Help();
      break;
    default:
      Help();
      break;
    }
  }
  return;
}



static void analyse_extraction( cpl_frame* rec_frame,  xsh_instrument* instr);

/*--------------------------------------------------------------------------
  Implementation
  --------------------------------------------------------------------------*/
static void analyse_extraction( cpl_frame* rec_frame, xsh_instrument* instr)
{
  const char* rec_name = NULL;
  xsh_rec_list* rec_list = NULL;
  int iorder;

  XSH_ASSURE_NOT_NULL( rec_frame);

  check( rec_name = cpl_frame_get_filename( rec_frame));

  printf("RECTIFY frame : %s\n", rec_name);
  check( rec_list = xsh_rec_list_load( rec_frame, instr));

  for(iorder=0; iorder< rec_list->size; iorder++){
    int order = 0, ilambda = 0;
    int nlambda = 0;
    float *flux = NULL;
    float *err = NULL; 
    double *lambda = NULL;
    char name[256];
    FILE* datfile = NULL;

    check( order = xsh_rec_list_get_order(rec_list, iorder)); 
    check( nlambda = xsh_rec_list_get_nlambda(rec_list, iorder));
    check( flux = xsh_rec_list_get_data1( rec_list, iorder));
    check( err = xsh_rec_list_get_errs1( rec_list, iorder));
    check( lambda = xsh_rec_list_get_lambda( rec_list, iorder));

    sprintf( name, "extract_order%d.dat",order);
    xsh_msg("Save file %s",name);
    datfile = fopen( name, "w");

    for(ilambda=0; ilambda < nlambda; ilambda++){
      fprintf( datfile,"%f %f\n",lambda[ilambda],flux[ilambda]);
    }
    fclose(datfile);

    sprintf( name, "extract_err_order%d.dat",order);
    xsh_msg("Save file %s",name);
    datfile = fopen( name, "w");

    for(ilambda=0; ilambda < nlambda; ilambda++){
      fprintf( datfile,"%f %f\n",lambda[ilambda],err[ilambda]);
    }
    fclose(datfile);
  }
  cleanup:
    xsh_rec_list_free( &rec_list); 
    return;
}

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

*/
int main( int argc, char **argv)
{
  /* Declarations */
  int ret = 0 ;
  xsh_instrument* instrument = NULL;
  xsh_extract_param extract_obj = { CLEAN_METHOD};
  cpl_propertylist *header= NULL; 
  const char *tag = NULL;
  cpl_frame* result = NULL;
  cpl_frame* result_eso = NULL;

  char* rec_name = NULL;
  cpl_frame* rec_frame = NULL;
  char* loc_name = NULL;
  cpl_frame* loc_frame = NULL; 
  XSH_ARM arm;
  int decode_bp=DECODE_BP_FLAG_DEF;
  xsh_interpolate_bp_param  ipol_bp_par={7 };

  /* 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, &extract_obj,&decode_bp);
  xsh_msg("argc=%d optind=%d",argc,optind);
  if ( (argc - optind) > 0 ) {
    rec_name = argv[optind];
    if ( (argc - optind) > 1){
      loc_name = argv[optind+1];
    }
  }
  else{
    Help();
  }
  rec_frame = cpl_frame_new();
  XSH_ASSURE_NOT_NULL (rec_frame);
  cpl_frame_set_filename( rec_frame, rec_name) ;

  check( header = cpl_propertylist_load( rec_name, 0));
  check( tag = xsh_pfits_get_pcatg( header));
  check( arm = xsh_pfits_get_arm( header))
;
  cpl_frame_set_level( rec_frame, CPL_FRAME_LEVEL_TEMPORARY);
  cpl_frame_set_group( rec_frame, CPL_FRAME_GROUP_RAW ) ;
  cpl_frame_set_tag( rec_frame, tag);

  /* Create instrument structure and fill */
  instrument = xsh_instrument_new();
  xsh_instrument_set_mode( instrument, XSH_MODE_IFU ) ;
  xsh_instrument_set_lamp( instrument, XSH_LAMP_QTH ) ;
  xsh_instrument_set_arm( instrument, arm);
  xsh_instrument_set_decode_bp(instrument,decode_bp);
  //xsh_msg("decode_bp=%d",decode_bp);
 

  if ( loc_name != NULL){
    loc_frame = cpl_frame_new();
    cpl_frame_set_filename( loc_frame, loc_name);
    cpl_frame_set_level( rec_frame, CPL_FRAME_LEVEL_TEMPORARY);
    cpl_frame_set_group( rec_frame, CPL_FRAME_GROUP_RAW );
  }
  /* Create REGION FILES for rectify */
  xsh_msg("Extract Parameters");
  xsh_msg("Rectified frame     : %s", rec_name);
  if (loc_name != NULL){
    xsh_msg("Localization table  : %s", loc_name);
  }

  check(result = xsh_extract_clean(rec_frame, loc_frame, instrument,
                                   &extract_obj,&ipol_bp_par,&result_eso,
                                   "test"));

  check( analyse_extraction( result, instrument));

  cleanup:
    
    xsh_instrument_free( &instrument);
    xsh_free_frame( &rec_frame);
    xsh_free_frame( &result);
    xsh_free_frame( &result_eso);
    xsh_free_frame( &loc_frame);
    xsh_free_frame( &rec_frame);
    xsh_free_propertylist( &header);

    if (cpl_error_get_code() != CPL_ERROR_NONE) {
      xsh_error_dump(CPL_MSG_ERROR);
      ret= 1;
    }
    TEST_END();
    return ret ;
}

/**@}*/
