/*                                                                           *
 *   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: 2011-12-09 10:09:26 $
 * $Revision: 1.18 $
 */

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

/*---------------------------------------------------------------------------*/
/**
 * @defgroup xsh_data_localization Localization
 * @ingroup data_handling
 */
/*---------------------------------------------------------------------------*/

/**@{*/


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

#include <math.h>
#include <xsh_dfs.h>
#include <xsh_data_localization.h>
#include <xsh_utils_table.h>
#include <xsh_error.h>
#include <xsh_msg.h>
#include <xsh_pfits.h>
#include <cpl.h>

/*----------------------------------------------------------------------------
                                 Function implementation
 ----------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/**
  @brief
    Create an empty localization list
  @return
    The order list structure
 */
/*---------------------------------------------------------------------------*/
xsh_localization* xsh_localization_create(void)
{
  xsh_localization* result = NULL;

  XSH_CALLOC(result, xsh_localization, 1);
  XSH_NEW_PROPERTYLIST(result->header);

  cleanup:
    if (cpl_error_get_code() != CPL_ERROR_NONE) {
      xsh_localization_free( &result);
    }  
    return result;
}
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/**
  @brief
    Load a localization list from a frame
  @param[in] frame 
    The table wich contains polynomials coefficients of the 
    orders
  @return
    The localization list structure
 */
/*---------------------------------------------------------------------------*/
xsh_localization* xsh_localization_load( cpl_frame* frame){
  cpl_table* table = NULL; 
  cpl_propertylist* header = NULL;
  const char* tablename = NULL;
  xsh_localization *result = NULL;
  int pol_degree = 0;
  cpl_size k;

  /* check input parameters */
  XSH_ASSURE_NOT_NULL( frame);

  /* get table filename */
  check( tablename = cpl_frame_get_filename( frame));

  XSH_TABLE_LOAD( table, tablename);

  check( result = xsh_localization_create());

  check( header = cpl_propertylist_load( tablename,0));
  check(cpl_propertylist_append( result->header, header));

  /* Get the polynomial degree */
  xsh_get_table_value( table, XSH_LOCALIZATION_TABLE_DEGPOL,
    CPL_TYPE_INT, 0, &pol_degree);
  result->pol_degree = pol_degree ;

  check( result->edguppoly = cpl_polynomial_new( 1));
  check( result->cenpoly = cpl_polynomial_new( 1));
  check( result->edglopoly = cpl_polynomial_new( 1));

  for( k = 0 ; k <= pol_degree ; k++ ) {
    char colname[32];
    float coef ;

    sprintf(colname, "%s%"CPL_SIZE_FORMAT, XSH_LOCALIZATION_TABLE_COLNAME_CENTER, k);
    check( xsh_get_table_value( table, colname, CPL_TYPE_FLOAT, 0, &coef));
    check( cpl_polynomial_set_coeff( result->cenpoly, &k, coef));

    sprintf(colname, "%s%"CPL_SIZE_FORMAT, XSH_LOCALIZATION_TABLE_COLNAME_EDGLO, k);
    check( xsh_get_table_value(table, colname, CPL_TYPE_FLOAT, 0, &coef));
    check( cpl_polynomial_set_coeff( result->edglopoly, &k,coef));

    sprintf(colname, "%s%"CPL_SIZE_FORMAT, XSH_LOCALIZATION_TABLE_COLNAME_EDGUP, k);
    check( xsh_get_table_value( table, colname, CPL_TYPE_FLOAT, 0, &coef));
    check( cpl_polynomial_set_coeff( result->edguppoly, &k, coef));
  }

  cleanup:
    if (cpl_error_get_code() != CPL_ERROR_NONE) {
      xsh_error_msg("can't load frame %s",cpl_frame_get_filename(frame));
      xsh_localization_free(&result);
    }
    xsh_free_propertylist( &header);
    XSH_TABLE_FREE( table);
    return result;  
}
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/**
  @brief 
    free memory associated to a localization_list
  @param[in] list 
    the localization_list to free
 */
/*---------------------------------------------------------------------------*/
void xsh_localization_free( xsh_localization **list)
{

  if (list && *list){
    /* free the list */
    xsh_free_polynomial(&(*list)->cenpoly);
    xsh_free_polynomial(&(*list)->edguppoly);
    xsh_free_polynomial(&(*list)->edglopoly);
    xsh_free_propertylist(&((*list)->header));
    cpl_free(*list);
    *list = NULL;
  }
}
/*---------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------*/
/**
  @brief 
    get header of the table
  @param[in] list 
    the localization_list
  @return 
    the header associated to the table
 */
/*---------------------------------------------------------------------------*/
cpl_propertylist * xsh_localization_get_header(xsh_localization *list)
{
  cpl_propertylist *res = NULL;

  XSH_ASSURE_NOT_NULL( list);
  res = list->header;
  cleanup:
    return res;
}
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/**
  @brief 
    save a localization to a frame
  @param[in] list 
    the localization_list structure wich contains polynomials
    coefficients  of the orders
  @param[in] filename 
    the name of the save file on disk
  @param[in] instrument
    instrument (arm) setting
  @return 
    a newly allocated frame
 */
/*---------------------------------------------------------------------------*/
cpl_frame* xsh_localization_save(xsh_localization *list,
				      const char* filename,
				      xsh_instrument * instrument)
{
  cpl_table* table = NULL;
  cpl_frame * result = NULL ;
  cpl_size k ;
  int pol_degree ;
  char colname[32] ;
  const char * tag = NULL ;

  /* check input parameters */
  XSH_ASSURE_NOT_NULL(list);
  XSH_ASSURE_NOT_NULL(filename);

  pol_degree = list->pol_degree;

  XSH_ASSURE_NOT_ILLEGAL( pol_degree >= 0 ) ;

  /* create a table */
  check(table = cpl_table_new( 1));

  /* Create as many column as needed, according to the polynomial degree */
  for( k = 0 ; k<= pol_degree ; k++ ) {

    sprintf(colname, "%s%"CPL_SIZE_FORMAT, XSH_LOCALIZATION_TABLE_COLNAME_CENTER, k);
    check(
	  cpl_table_new_column(table, colname, CPL_TYPE_FLOAT));
    sprintf(colname, "%s%"CPL_SIZE_FORMAT, XSH_LOCALIZATION_TABLE_COLNAME_EDGUP, k);
    check(
	  cpl_table_new_column(table, colname, CPL_TYPE_FLOAT));
    sprintf(colname, "%s%"CPL_SIZE_FORMAT, XSH_LOCALIZATION_TABLE_COLNAME_EDGLO, k);
    check(
	  cpl_table_new_column(table, colname, CPL_TYPE_FLOAT));
  }
  check( cpl_table_new_column( table, XSH_LOCALIZATION_TABLE_DEGPOL,
			       CPL_TYPE_INT ) ) ;

  
  for( k = 0 ; k <= pol_degree ; k++ ) {
    double coef ;

    /* Get and Write coef from center polynomial */
    check(coef = cpl_polynomial_get_coeff( list->cenpoly, &k));
    sprintf(colname, "%s%"CPL_SIZE_FORMAT, XSH_LOCALIZATION_TABLE_COLNAME_CENTER, k);
    check(cpl_table_set( table, colname, 0, coef));

    /* Get and Write coef from upper polynomial */
    check(coef = cpl_polynomial_get_coeff( list->edguppoly, &k));
    sprintf(colname, "%s%"CPL_SIZE_FORMAT, XSH_LOCALIZATION_TABLE_COLNAME_EDGUP, k);
    check(cpl_table_set( table, colname, 0, coef));

    /* Get and Write coef from lower polynomial */
    check(coef = cpl_polynomial_get_coeff( list->edglopoly, &k));
    sprintf(colname, "%s%"CPL_SIZE_FORMAT, XSH_LOCALIZATION_TABLE_COLNAME_EDGLO, k);
    check(cpl_table_set( table, colname, 0, coef));
  }

  check( cpl_table_set(table, XSH_LOCALIZATION_TABLE_DEGPOL, 0,
    pol_degree));
  /* create fits file */
  check( cpl_table_save( table, list->header, NULL, filename, CPL_IO_DEFAULT));
  /* Create the frame */
  tag = XSH_GET_TAG_FROM_ARM( XSH_LOCALIZATION, instrument);
  check(result=xsh_frame_product(filename,
				 tag,
				 CPL_FRAME_TYPE_TABLE,
				 CPL_FRAME_GROUP_PRODUCT,
				 CPL_FRAME_LEVEL_TEMPORARY));

  cleanup:
    XSH_TABLE_FREE(table);
    return result ;
}

/**@}*/
