/*                                                                            *
 *   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-04-26 14:10:08 $
 * $Revision: 1.19 $
 */
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

/*--------------------------------------------------------------------------*/
/**
 * @defgroup test_xsh_detect_continuum Test Detect Continuum 
 * @ingroup unit_tests
 *
 */
/*--------------------------------------------------------------------------*/
/**@{*/

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


#include <cpl.h>
#include <xsh_data_instrument.h>
#include <xsh_pfits.h>
#include <xsh_msg.h>
#include <xsh_utils.h>
#include <xsh_data_order.h>
#include <tests.h>
#include <math.h>
#include <xsh_cpl_size.h>
/*---------------------------------------------------------------------------
                            Defines
 ---------------------------------------------------------------------------*/
#define MODULE_ID "XSH_DETECT_CONTINUUM"
/*---------------------------------------------------------------------------
                         Functions prototypes
 ---------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------*/
/**
  @brief    Unit test of XSH_DETECT_CONTINUUM
  @return   0 if tests passed successfully

  Test the Data Reduction Library function XSH_DETECT_CONTINUUM
 */
/*--------------------------------------------------------------------------*/

/*
   1 polynome (same for all orders)
   constant coeff incresed by 20 for each order
*/

static const double poly0_coeff[] = {
  280., 0.3, -0.0025 } ;
static const double step = 40. ;

static int nx = 400, ny = 400 ;
static int starty = 10, endy = 380 ;
static int dimension = 1, degree = 2, width = 10 ;
static int norder = 3 ;
static double exptime = 1. ;
static const char * img_name = "dtc_img.fits" ;
static const char * tbl_name = "dtc_tbl.fits" ;
static const char * dtc_pre_name = "dtc_img_pre.fits" ;

static void verify_order_table( cpl_frame * result )
{
  const char *hname ;

  cpl_propertylist * header = NULL ;
  double residavg = 0. ;

  xsh_msg( " ====== verify_order_tables" ) ;

  /* Get propertylist of new order_table
     check RESIDAVG, should be < 1 pixel
  */
  check( hname = cpl_frame_get_filename( result ) ) ;
  check( header = cpl_propertylist_load( hname, 0 ) ) ;
  check(xsh_get_property_value (header, QC_ORD_ORDERPOS_RESIDAVG,
				CPL_TYPE_DOUBLE, &residavg ) ) ;

  assure( residavg < 1., CPL_ERROR_ILLEGAL_INPUT, "Error Too large" ) ;
  xsh_msg( "   Orders Detected OK, RESIDAVG = %lf", residavg ) ;

 cleanup:
  xsh_free_propertylist(&header);
  return ;
}

int main(void)
{
  xsh_instrument* instrument = NULL;
  xsh_order_list * list = NULL ;
  cpl_polynomial * poly0 = NULL ;
  cpl_polynomial * poly1 = NULL ;
  cpl_polynomial * poly2 = NULL ;
  cpl_image *image = NULL ;
  cpl_image *bias = NULL;
  cpl_frame * img_frame = NULL, * tbl_frame = NULL, * dtc_frame = NULL,
    * result_frame = NULL ;
  xsh_pre * img_pre = NULL ;
  xsh_clipping_param dcn_clipping ;
  xsh_detect_continuum_param detect_param;

  XSH_INSTRCONFIG *iconfig ;
  cpl_propertylist * img_header=NULL ;
  cpl_frame* resid_frame=NULL;

  TESTS_INIT_WORKSPACE(MODULE_ID);
  TESTS_INIT(MODULE_ID);
  xsh_msg("detect_continuum");
  instrument = xsh_instrument_new() ;
  xsh_instrument_set_mode( instrument, XSH_MODE_SLIT ) ;
  xsh_instrument_set_arm( instrument, XSH_ARM_VIS ) ;
  xsh_instrument_set_lamp( instrument, XSH_LAMP_UNDEFINED ) ;
  xsh_instrument_set_recipe_id( instrument, "xsh_orderpos" ) ;

  xsh_msg( "   recipe_id: %s", instrument->recipe_id ) ;

  iconfig = xsh_instrument_get_config( instrument ) ;
  iconfig->orders = norder ;

  xsh_msg( "Create Order List with %d orders", norder ) ;
  check( list = create_order_list( norder, instrument ) ) ;

  xsh_msg( "Create polynomials of degree %d", degree ) ;
  poly0 = cpl_polynomial_new( dimension ) ;
  poly1 = cpl_polynomial_new( dimension ) ;
  poly2 = cpl_polynomial_new( dimension ) ;

  /* Set polynomial coefficients */
  {
    cpl_size i ;
    i = 0 ;

    cpl_polynomial_set_coeff( poly0, &i, poly0_coeff[i] ) ;
    cpl_polynomial_set_coeff( poly1, &i, poly0_coeff[i] + step ) ;
    cpl_polynomial_set_coeff( poly2, &i, poly0_coeff[i] + 2*step ) ;

    for( i = 1 ; i<= degree ; i++ ) {
      cpl_polynomial_set_coeff( poly0, &i, poly0_coeff[i] ) ;
      cpl_polynomial_set_coeff( poly1, &i, poly0_coeff[i] ) ;
      cpl_polynomial_set_coeff( poly2, &i, poly0_coeff[i] ) ;
    }
  }

  xsh_msg( "Add to order list" ) ;
  add_to_order_list( list, 0, 1, poly0, width, starty, endy ) ;
  add_to_order_list( list, 1, 2, poly1, width, starty, endy ) ;
  add_to_order_list( list, 2, 3, poly2, width, starty, endy ) ;

  xsh_order_list_dump( list, "orders.dmp" ) ;

  /* Save image and create Frame accordingly */
  img_frame = cpl_frame_new() ;
  img_header = mkHeader( iconfig, nx, ny, exptime ) ;

  check( image = create_order_image( list, nx, ny ) ) ;
  cpl_image_save( image, img_name, CPL_BPP_IEEE_DOUBLE, img_header,
		  CPL_IO_DEFAULT);

  cpl_frame_set_filename( img_frame, img_name ) ;
  cpl_frame_set_tag( img_frame, "ORDERDEF_VIS_D2" );
  cpl_frame_set_level( img_frame, CPL_FRAME_LEVEL_TEMPORARY);
  cpl_frame_set_group( img_frame, CPL_FRAME_GROUP_RAW ) ;

  /* Save this frame as a PRE frame */
  bias = xsh_test_create_bias_image( "BIAS.fits" ,nx, ny, instrument);
  check( img_pre = xsh_pre_create( img_frame, NULL, bias, instrument,0,CPL_FALSE));
  xsh_msg( "Saving PRE image \"%s\"", dtc_pre_name ) ;
  check_msg( dtc_frame = xsh_pre_save( img_pre, dtc_pre_name, "TEST",1 ),
	     "Cant save pre structure" ) ;
  cpl_frame_set_filename( dtc_frame, dtc_pre_name ) ;
  cpl_frame_set_tag( dtc_frame, "ORDERDEF_UVB_D2" );
  cpl_frame_set_level( dtc_frame, CPL_FRAME_LEVEL_TEMPORARY);
  cpl_frame_set_group( dtc_frame, CPL_FRAME_GROUP_RAW ) ;

  /* Save order table frame */
  check( tbl_frame = xsh_order_list_save( list, instrument, tbl_name,"ORDERDEF_UVB_D2",ny) ) ;


  /* Now detect continuum */
  dcn_clipping.sigma = 2.5 ;
  dcn_clipping.niter = 5 ;
  dcn_clipping.frac = 0.7 ;
  //The following value is crucial to the success of the test 
  //we use the min allowed to make the test pass
  dcn_clipping.res_max = 0.4 ;

  detect_param.search_window = 30;
  detect_param.running_window = 7;
  detect_param.fit_window = 10;
  detect_param.poly_degree = 2;
  detect_param.poly_step = 2;
  detect_param.fit_threshold = 1.0;

  xsh_debug_level_set( XSH_DEBUG_LEVEL_LOW ) ;
  //  cpl_msg_set_level( CPL_MSG_DEBUG ) ;
  check (result_frame = xsh_detect_continuum( dtc_frame, tbl_frame, NULL,
					      &detect_param,
					      &dcn_clipping,
					      instrument,&resid_frame) ) ;

  /* Now Verify order tables */
  check( verify_order_table( result_frame ) ) ;

  cleanup:
  xsh_free_propertylist(&img_header);
  xsh_free_polynomial(&poly0);
  xsh_free_polynomial(&poly1);
  xsh_free_polynomial(&poly2);

  xsh_free_frame(&img_frame);
  xsh_free_frame(&dtc_frame);
  xsh_free_frame(&tbl_frame);
  xsh_free_frame(&result_frame);

  xsh_free_frame(&resid_frame);
  xsh_order_list_free(&list);
  xsh_free_image(&image);
  xsh_free_image(&bias);
  xsh_pre_free(&img_pre);
  xsh_instrument_free(&instrument);
  TESTS_CLEAN_WORKSPACE(MODULE_ID);
    if (cpl_error_get_code() != CPL_ERROR_NONE) {
      xsh_error_dump(CPL_MSG_ERROR);
      return 1;
    } 
    else {
      return 0;
    }

}

/**@}*/
