/*                                                                            *
 *   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-12-07 16:51:34 $
 * $Revision: 1.10 $
 * $Name: not supported by cvs2svn $
 */
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

/*--------------------------------------------------------------------------*/
/**
 * @defgroup test_xsh_test_order     Test Data type ORDER functions
 * @ingroup unit_tests
 *
 */
/*--------------------------------------------------------------------------*/
/**@{*/

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


#include <xsh_data_order.h>
#include <xsh_error.h>
#include <xsh_msg.h>
#include <xsh_data_instrument.h>
#include <xsh_dfs.h>
#include <xsh_pfits.h>
#include <tests.h>
#include <xsh_data_spectralformat.h>
#include <xsh_data_wavesol.h>
#include <xsh_data_arclist.h>
#include <xsh_utils_table.h>
#include <cpl.h>
#include <math.h>
#include <getopt.h>

/*---------------------------------------------------------------------------
                            Defines
 ---------------------------------------------------------------------------*/
#define MODULE_ID "XSH_DATA_WAVE_TAB_2D"

enum {
  LAMBDA_STEP_OPT, SLIT_STEP_OPT, BINX_OPT, BINY_OPT,DEBUG_OPT, HELP_OPT
} ;

static float lambda_step = 0.5;
static float slit_step = 1.458;
int binx =1;
int biny =1;

static struct option LongOptions[] = {
  {"lambda-step", required_argument, 0, LAMBDA_STEP_OPT},
  {"slit-step", required_argument, 0, SLIT_STEP_OPT},
  {"binx", required_argument, 0, BINX_OPT},
  {"biny", required_argument, 0, BINY_OPT},
  {"debug", required_argument, 0, DEBUG_OPT},
  {"help", 0, 0, HELP_OPT},
  {NULL, 0, 0, 0}
} ;


static void Help( void )
{
  puts ("Unitary test of wave tab 2d");
  puts( "Usage : ./the_xsh_data_wave_tab_2d [options] <SOF>");

  puts( "Options" ) ;
  puts( " --binx=<n>         : Binning in X (default 1)" );
  puts( " --biny=<n>         : Binning in Y (default 1)" );
  puts( " --lambda-step=<n>  : Step in lambda. Default 0.2" );
  puts( " --slit-step=<n>    : Step in slit. Default 0.2" );
  puts( " --debug=<n>        : Level of debug LOW | MEDIUM | HIGH [MEDIUM]" );
  puts( " --help             : What you see" ) ;

  puts( "The input files argument MUST be in this order:" ) ;
  puts( " 1. SOF [WAVE_TAB_2D, SPECTRAL_FORMAT, ARC_LIST]");
  TEST_END();
  exit(0);
}

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

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

  while( (opt = getopt_long( argc, argv, "debug:help",
			     LongOptions, &option_index )) != EOF )
    switch( opt ) {
    case LAMBDA_STEP_OPT:
      lambda_step = atof(optarg);
      break ;
    case SLIT_STEP_OPT:
      slit_step = atof(optarg);
      break ;
    case  BINX_OPT:
      binx = atoi(optarg);
    case BINY_OPT:
      biny = atoi(optarg);
      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 HELP_OPT:
      Help();
      break;
    default:
      break;
    }
}

/*--------------------------------------------------------------------------*/
/**
  @brief
    Unit test of xsh_data_wave_tab_2d
  @return
    0 if success

*/
/*--------------------------------------------------------------------------*/
int main(int argc, char** argv)
{
  int ret = 0;
  int i;
  float j,k;
  xsh_instrument * instrument = NULL ;
  cpl_frameset* set = NULL;
  char *sof_name = NULL;
  cpl_frame *wave_tab_2d_frame = NULL;
  cpl_frame *spectralformat_frame = NULL;
  cpl_frame *arclist_frame = NULL;
  xsh_spectralformat_list *spec_list = NULL;
  xsh_wavesol *wave_tab_2d = NULL;
  xsh_arclist* arclist = NULL;
  FILE* wave_tab_2d_file = NULL;
  FILE* wave_tab_2d_dat_file = NULL;

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

  HandleOptions( argc, argv);

  /* Analyse parameters */
  if ( (argc-optind) >= 1) {
    sof_name = argv[optind];
    /* Create frameset from sof */
    check( set = sof_to_frameset( sof_name));

    /* Validate frame set */
    check( instrument = xsh_dfs_set_groups( set));

    check( wave_tab_2d_frame = xsh_find_wave_tab_2d( set, instrument));
    check( spectralformat_frame = xsh_find_spectral_format( set, instrument));
    arclist_frame = xsh_find_arc_line_list( set, instrument); 
  }
  else{
    Help();
  }
  xsh_msg("Wave tab 2d     : %s", cpl_frame_get_filename(wave_tab_2d_frame));
  xsh_msg("Spectral format : %s", cpl_frame_get_filename(spectralformat_frame));
  if ( arclist_frame != NULL){
    xsh_msg("Arclines     : %s", cpl_frame_get_filename( arclist_frame));
  }
  xsh_msg(" Options : lambda-step %f slit-step %f", lambda_step, slit_step);

  check( spec_list = xsh_spectralformat_list_load( spectralformat_frame,
    instrument));
  check( wave_tab_2d = xsh_wavesol_load( wave_tab_2d_frame, instrument));
  xsh_wavesol_set_bin_x( wave_tab_2d, binx);
  xsh_wavesol_set_bin_y( wave_tab_2d, biny);
  xsh_msg("bin %dx%d",binx, biny);
  xsh_msg("Wavesol lambda (%f,%f)", wave_tab_2d->min_lambda, 
    wave_tab_2d->max_lambda);
  xsh_msg("Wavesol order (%f,%f)", wave_tab_2d->min_order,
    wave_tab_2d->max_order);
  xsh_msg("Wavesol slit (%f,%f)", wave_tab_2d->min_slit,
    wave_tab_2d->max_slit);

  wave_tab_2d_file = fopen( "WAVE_TAB_2D.reg", "w");
  wave_tab_2d_dat_file = fopen( "WAVE_TAB_2D.dat", "w");
  fprintf( wave_tab_2d_file, "# Region file format: DS9 version 4.0\n"\
    "global color=red font=\"helvetica 10 normal\""\
    "select=1 highlite=1 edit=1 move=1 delete=1 include=1 fixed=0 "\
    "source\nimage\n");
  fprintf( wave_tab_2d_dat_file, "# x y lambda slit\n");

  if ( arclist_frame == NULL){
    for( i=0; i< spec_list->size; i++){
      double absorder;
      float lambda_min, lambda_max;
      float lambda_min_full, lambda_max_full;

      absorder= (double)spec_list->list[i].absorder;
      lambda_min = spec_list->list[i].lambda_min;
      lambda_max = spec_list->list[i].lambda_max;
      lambda_min_full = spec_list->list[i].lambda_min_full;
      lambda_max_full = spec_list->list[i].lambda_max_full;
      xsh_msg("order %f lambda %f->%f-%f<-%f",absorder, lambda_min_full,
        lambda_min, lambda_max, lambda_max_full);

      for(j=lambda_min_full; j <= lambda_max_full; j+=lambda_step){
        double x, y;
        const char* full_lambda_color = "yellow";
        const char* lambda_color = "red";
        const char* color = NULL;

        if ( (j < lambda_min)|| (j > lambda_max) ){
          color = full_lambda_color;
        }
        else{
          color = lambda_color;
        }
        check( x = xsh_wavesol_eval_polx( wave_tab_2d, j, absorder, 0.0));
        check( y = xsh_wavesol_eval_poly( wave_tab_2d, j, absorder, 0.0));

      
        fprintf( wave_tab_2d_file, "point(%f,%f) #point=cross color=%s font="\
            "\"helvetica 10 normal\" text={ %.3f}\n", x, y, color, j);
        fprintf( wave_tab_2d_dat_file, "%f %f %f %f\n", x, y, j, 0.0);

        for( k=wave_tab_2d->min_slit; k <= wave_tab_2d->max_slit; k+=slit_step){
          check( x = xsh_wavesol_eval_polx( wave_tab_2d, j, absorder, k));
          check( y = xsh_wavesol_eval_poly( wave_tab_2d, j, absorder, k));
          fprintf( wave_tab_2d_file, "point(%f,%f) #point=cross color=green font="\
            "\"helvetica 10 normal\" text={ %.3f}\n", x, y, k);
          fprintf( wave_tab_2d_dat_file, "%f %f %f %f\n", x, y, j, k);
        }
      }
    }
  }
  else{
    int size;

    arclist = xsh_arclist_load( arclist_frame);
    size = arclist->size;

    for( i=0; i< size; i++){
      float lambda = 0.0;
      cpl_vector *orders = NULL;
      int order_size;

      lambda = xsh_arclist_get_wavelength( arclist, i);
      orders = xsh_spectralformat_list_get_orders( spec_list, lambda);
      order_size = cpl_vector_get_size( orders);

      for( j=0; j < order_size; j++){
        double absorder;
        double x, y;

        absorder = cpl_vector_get( orders, j);

        check( x = xsh_wavesol_eval_polx( wave_tab_2d, lambda, absorder, 0.0));
        check( y = xsh_wavesol_eval_poly( wave_tab_2d, lambda, absorder, 0.0));

        fprintf( wave_tab_2d_file, "point(%f,%f) #point=cross color=red font="\
            "\"helvetica 10 normal\" text={ %.3f}\n", x, y, lambda);
        fprintf( wave_tab_2d_dat_file, "%f %f %f %f\n", x, y, lambda, 0.0);

        for( k=slit_step; k < wave_tab_2d->max_slit; k+=slit_step){
          check( x = xsh_wavesol_eval_polx( wave_tab_2d, lambda, absorder, k));
          check( y = xsh_wavesol_eval_poly( wave_tab_2d, lambda, absorder, k));
          fprintf( wave_tab_2d_file, "point(%f,%f) #point=cross color=green font="\
            "\"helvetica 10 normal\" text={ %.3f}\n", x, y, k);
          fprintf( wave_tab_2d_dat_file, "%f %f %f %f\n", x, y, lambda, k);
          check( x = xsh_wavesol_eval_polx( wave_tab_2d, lambda, absorder, -k));
          check( y = xsh_wavesol_eval_poly( wave_tab_2d, lambda, absorder, -k));
                    fprintf( wave_tab_2d_file, "point(%f,%f) #point=cross color=green font="\
            "\"helvetica 10 normal\" text={ %.3f}\n", x, y, -k);
          fprintf( wave_tab_2d_dat_file, "%f %f %f %f\n", x, y, lambda, -k);
        }
      }
      xsh_free_vector( &orders);
    }
  }
    

  cleanup:
    xsh_instrument_free( &instrument);
    xsh_free_frameset( &set);

    xsh_arclist_free( &arclist);
    xsh_spectralformat_list_free( &spec_list);
    xsh_wavesol_free( &wave_tab_2d);

    TEST_END();
    if (cpl_error_get_code() != CPL_ERROR_NONE) {
      xsh_error_dump(CPL_MSG_ERROR);
      ret  = 1;
    }
    if ( NULL !=  wave_tab_2d_dat_file) {
       fclose( wave_tab_2d_dat_file);
    }
    if ( NULL !=  wave_tab_2d_file) {
       fclose( wave_tab_2d_file);
    }

    return ret ;
}

/**@}*/
