/*                                                                              *
 *   This file is part of the ESO UVES Pipeline                                 *
 *   Copyright (C) 2004,2005 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       *
 *                                                                              */
 
/*
 */

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

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

#include <uves_error.h>
#include <cpl_test.h>
#include <cpl.h>
#include <uves_pfits.h>
#include <uves_msg.h>
#include <getopt.h>
/*-----------------------------------------------------------------------------
                                Defines
 -----------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
                            Functions prototypes
 -----------------------------------------------------------------------------*/


/*----------------------------------------------------------------------------*/
/**
 * @defgroup  uves_flux_std_catalog_update  UVES library unit tests
 */
/*----------------------------------------------------------------------------*/
/**@{*/
/**
@brief this function test the gaussian fitting
*/


static cpl_table* crea_star_entry(const char* fname, const char* object,
		const char* type, const double vmag, const char* ra_2000,
		const char* dec_2000, const double RA_DEG,
		const double DEC_DEG, const char* fits_file_name)
{
	cpl_error_code err = CPL_ERROR_NONE;

	cpl_propertylist* phead = cpl_propertylist_load(fname,0);
	cpl_propertylist* xhead = cpl_propertylist_load(fname,1);

	cpl_table* tbl_add = NULL;
	cpl_table* tbl_cat = NULL;
	tbl_add = cpl_table_load(fits_file_name, 1,0);
	tbl_cat = cpl_table_load(fname, 1,0);
	int ndata = cpl_table_get_nrow(tbl_add);
	/* Relevant columns are:
	"OBJECT"  12A []
	"TYPE"     5A []
	"VMAG"     1E [MAG]
	"RA_2000"  11A [HMS]
	"DEC_2000" 11A [DMS]
	"RA_DEG"   1D  [degree]
	"DEC_DEG"  1D  [degree]
	"NDATA"    J   []
	LAMBDA     E   [Angstrom]
	BIN_WIDTH  E   [Angstrom]
	F_LAMBDA   E   erg/s/cm^2/A
	*/
	cpl_table* table = cpl_table_new(1);
	cpl_table_copy_structure(table,tbl_cat);

	cpl_table_set_string(table, "OBJECT", 0, object);

	cpl_table_set_string(table, "TYPE", 0, type);

	cpl_table_set_float(table, "VMAG", 0, vmag);

	cpl_table_set_string(table, "RA_2000", 0, ra_2000);

	cpl_table_set_string(table, "DEC_2000", 0, dec_2000);

	cpl_table_set_double(table, "RA_DEG", 0, RA_DEG);

    cpl_table_set_double(table, "DEC_DEG", 0, DEC_DEG);

	cpl_table_set_int(table, "NDATA", 0, ndata);

	double* plambda = cpl_table_get_data_double(tbl_add,"LAMBDA");
	double* pbin_width = cpl_table_get_data_double(tbl_add,"BIN_WIDTH");
	double* pflambda = cpl_table_get_data_double(tbl_add,"FLUX");
	cpl_array* a_lambda = cpl_array_new(ndata,CPL_TYPE_FLOAT);
	cpl_array* a_bin_width = cpl_array_new(ndata,CPL_TYPE_FLOAT);
	cpl_array* a_flambda = cpl_array_new(ndata,CPL_TYPE_FLOAT);


	for (int i = 0; i < ndata; i++) {
		cpl_array_set_float(a_lambda, i, (float)plambda[i]);
		cpl_array_set_float(a_bin_width, i, (float)pbin_width[i]);
		cpl_array_set_float(a_flambda, i, (float)pflambda[i]);
	}

    cpl_table_erase_column(table,"LAMBDA");
	cpl_table_new_column_array(table, "LAMBDA", CPL_TYPE_FLOAT,ndata);
	cpl_table_set_array(table, "LAMBDA", 0, a_lambda);
	cpl_table_set_column_unit(table,"LAMBDA","Angstrom");

	cpl_table_erase_column(table,"BIN_WIDTH");
	cpl_table_new_column_array(table, "BIN_WIDTH", CPL_TYPE_FLOAT,ndata);
	cpl_table_set_array(table, "BIN_WIDTH", 0, a_bin_width);
	cpl_table_set_column_unit(table,"BIN_WIDTH","Angstrom");

	cpl_table_erase_column(table,"F_LAMBDA");
	cpl_table_new_column_array(table, "F_LAMBDA", CPL_TYPE_FLOAT,ndata);
	cpl_table_set_array(table, "F_LAMBDA", 0, a_flambda);
	cpl_table_set_column_unit(table,"F_LAMBDA","erg/s/cm^2/A");

	cpl_table_save(table,phead,xhead,"pippo.fits",CPL_IO_DEFAULT);
    cpl_propertylist_delete(phead);
    cpl_propertylist_delete(xhead);
	cpl_table_delete(tbl_add);
	cpl_table_delete(tbl_cat);
    cpl_array_delete(a_lambda);
    cpl_array_delete(a_bin_width);
    cpl_array_delete(a_flambda);
	return table;
}
static cpl_error_code remove_star(const char* fname, const char* object)
{
	cpl_error_code err = CPL_ERROR_NONE;

	cpl_propertylist* phead = cpl_propertylist_load(fname,0);
    cpl_propertylist* xhead = cpl_propertylist_load(fname,1);
	cpl_table* tab_cat = cpl_table_load(fname,1,0);
	int nrow_cat = cpl_table_get_nrow(tab_cat);
	for(int i=0; i < nrow_cat; i++) {
		if(strcmp(object, cpl_table_get_string(tab_cat, "OBJECT", i)) == 0 ) {
			cpl_table_set_invalid(tab_cat,"OBJECT",i);
		}
	}
	cpl_table_erase_invalid(tab_cat);
	cpl_table_save(tab_cat,phead,xhead,fname,CPL_IO_DEFAULT);
	cpl_table_delete(tab_cat);
	cpl_propertylist_delete(phead);
	cpl_propertylist_delete(xhead);
	return err;
}
static cpl_error_code add_star(const char* fname, cpl_table* tab_add)
{
	cpl_error_code err = CPL_ERROR_NONE;

    cpl_table* tab_cat = cpl_table_load(fname,1,0);
    cpl_propertylist* phead = cpl_propertylist_load(fname,0);
    cpl_propertylist* xhead = cpl_propertylist_load(fname,1);

    int nrow_cat = cpl_table_get_nrow(tab_cat);

    int depth_cat = cpl_table_get_column_depth(tab_cat,"F_LAMBDA");
    int depth_add = cpl_table_get_column_depth(tab_add,"F_LAMBDA");
    if( depth_add > depth_cat) {
    	for(int i=0; i < nrow_cat; i++) {

    		cpl_table_set_column_depth(tab_cat,"LAMBDA",depth_add);
    		cpl_table_set_column_depth(tab_cat,"BIN_WIDTH",depth_add);
    		cpl_table_set_column_depth(tab_cat,"F_LAMBDA",depth_add);

    	}
    } else {
    	cpl_table_set_column_depth(tab_add,"LAMBDA",depth_cat);
    	cpl_table_set_column_depth(tab_add,"BIN_WIDTH",depth_cat);
    	cpl_table_set_column_depth(tab_add,"F_LAMBDA",depth_cat);
    }
    cpl_table_insert(tab_cat,tab_add,nrow_cat+1);

	if (tab_cat)
	{

		cpl_table_save(tab_cat,phead,xhead,fname,CPL_IO_DEFAULT);
	}
	else
	{

		err = CPL_ERROR_FILE_IO;
	}
	cpl_table_delete(tab_cat);
	cpl_propertylist_delete(phead);
    cpl_propertylist_delete(xhead);
	return err;
}
/*----------------------------------------------------------------------------*/
/**
  @brief   Various tests of low-level library functions

  Currently, only 2d gaussian fitting (@c uves_fit_gaussian_2d which calls
  @c uves_fit_gaussian_1d_image which
  calls @c irplib_fit_gaussian_1d which calls Levenberg-Marquardt routine) is 
  tested.
**/
/*----------------------------------------------------------------------------*/

int main(int argc, char * const argv[])
{
    /* Initialize CPL + UVES messaging */
    cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_WARNING);

    int print_usage = 0;

 	int opt = 0;
 	const char* flux_std_cat_name=NULL;
 	const char* flux_std_add_name=NULL;
 	uves_msg_warning("argc=%d",argc);
 	if (argc < 3)
 	{
 		print_usage = 1;
 	}
 	else
 	{
 		flux_std_cat_name = argv[1];
 		flux_std_add_name = argv[6];

 	}
 	uves_msg_warning("flux_std_cat_name=%s",flux_std_cat_name);
 	uves_msg_warning("flux_std_add_name=%s",flux_std_add_name);
 	if (flux_std_cat_name == NULL || flux_std_add_name == NULL)
 	{
 		print_usage = 1;
 	}
 	if(print_usage)
 	{
 		fprintf(stderr, "usage: %s catalog_name [-l | -a star_name RA DEC "
 				"ref_fits_file.fits | -r star_name]\n"
 				"-a option creates a new catalog, if catalog_name is not "
 				"presented\n", argv[0]);
 		return 0;
 	}
 	opt = getopt(argc,argv,"lr:a:");

 	uves_msg_warning("opt=%d",opt);
 	cpl_error_code err;
 	int pindex=0;
	if (opt != -1)
	{
		switch (opt)
		{
		case 'l':
			printf("LIST: Not implemented yet\n");

			break;
		case 'r':
		{
			const char* star_name = optarg;
			printf("REMOVE [%s]\n", star_name);
			remove_star(flux_std_cat_name, star_name);

		}
			break;
		case 'a':
		{
			const char* star_name = optarg;
			const char* type = argv[optind];
			const double vmag = atof(argv[optind+1]);
			const char* RA = argv[optind+2];
			const char* DEC = argv[optind+3];
			double RA_DEG = atof(argv[optind+4]);
			double DEC_DEG = atof(argv[optind+5]);
			const char* fits_file = argv[optind+6];

			cpl_table* tab;
			printf("On catalog [%s] add object [%s] type[%s] vmag [%f] coord_2000[%s,%s] coord[%f:%f] file:%s\n",
					flux_std_cat_name, star_name,  type,    vmag,     RA, DEC,          RA_DEG,DEC_DEG, fits_file);

			tab = crea_star_entry(flux_std_cat_name, star_name, type, vmag,
					RA, DEC, RA_DEG, DEC_DEG, fits_file);

			err = add_star(flux_std_cat_name, tab);


			if (err == CPL_ERROR_NONE)
			{
				printf ("save to [%s]\n", flux_std_cat_name);

			}
			else
			{
				printf("error during add\n");
			}
			cpl_table_delete(tab);
		}
			break;
		default:
			fprintf(stderr, " Urecognized option, usage: %s catalog_name [-l | -a star_name RA DEC ref_fits_file.fits | -r star_name]\n", argv[0]);
			break;

		}
	}



  cleanup:
    return cpl_test_end(0);
}


/**@}*/
