/* $Id: amber_raw_to_fitsimage.c,v 1.17 2013-09-16 14:56:43 agabasch Exp $
 *
 * This file is part of the AMBER Pipeline
 * Copyright (C) 2002,2003 European Southern Observatory
 *
 * This program 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, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * $Author: agabasch $
 * $Date: 2013-09-16 14:56:43 $
 * $Revision: 1.17 $
 * $Name: not supported by cvs2svn $
 */

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

/* AMDLIB usage switch */
#define USE_AMDLIB YES

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

#include <math.h>
#include <cpl.h>
#include <string.h>
#include "amdrs.h"

#ifdef USE_AMDLIB	

/* amdlib structures */
amdlibERROR_MSG       errMsg;
amdlibBAD_PIXEL_MAP   badPixels;
amdlibFLAT_FIELD_MAP  flatField;
static  amdlibRAW_DATA        rawData;
amdlibP2VM_INPUT_DATA p2vmData;
amdlibP2VM_MATRIX     p2vm;

#endif

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

static int amber_raw_to_fitsimage_create(cpl_plugin *) ;
static int amber_raw_to_fitsimage_exec(cpl_plugin *) ;
static int amber_raw_to_fitsimage_destroy(cpl_plugin *) ;
static int amber_raw_to_fitsimage(cpl_parameterlist *, cpl_frameset *) ;


/*-----------------------------------------------------------------------------
                            Static variables
 -----------------------------------------------------------------------------*/

/*
static struct {
	 Inputs
	int         bool_option ;
	char        str_option[512] ;

	 Outputs
	double      qc_param ;
} amber_raw_to_fitsimage_config ;
 */

static char amber_raw_to_fitsimage_man[] =
"The main purpose of this recipe is to convert the imaging sections of a\n"
"amber raw files into a fits-cube and a fits-images showing the 5 channels.\n"
"This recipe is able to process all amber raw files with a DATA column in the\n"
"IMAGING_DATA extension, i.e. most of the amber raw files. Therefore no\n"
"special classification tag needs to be given to the SOF. Moreover, the SOF\n"
"should include only one amber raw file.\n";

/*-----------------------------------------------------------------------------
                                Functions code
 -----------------------------------------------------------------------------*/


/*----------------------------------------------------------------------------*/
/**
  @brief    Build the list of available plugins, for this module. 
  @param    list    the plugin list
  @return   0 if everything is ok

  This function is exported.
 */
/*----------------------------------------------------------------------------*/
int cpl_plugin_get_info(cpl_pluginlist * list)
{
	cpl_recipe  *   recipe = cpl_calloc(1, sizeof(*recipe)) ;
	cpl_plugin  *   plugin = &recipe->interface ;

	cpl_plugin_init(plugin,
			CPL_PLUGIN_API,
			AMBER_BINARY_VERSION,
			CPL_PLUGIN_TYPE_RECIPE,
			"amber_raw_to_fitsimage",
			"AMBER raw data display",
			amber_raw_to_fitsimage_man,
			"Tom Licha",
			PACKAGE_BUGREPORT,
			"GP",
			amber_raw_to_fitsimage_create,
			amber_raw_to_fitsimage_exec,
			amber_raw_to_fitsimage_destroy) ;

	cpl_pluginlist_append(list, plugin) ;

	return 0;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Setup the recipe options    
  @param    plugin  the plugin
  @return   0 if everything is ok

  Create the recipe instance and make it available to the application using the 
  interface. 
 */
/*----------------------------------------------------------------------------*/
static int amber_raw_to_fitsimage_create(cpl_plugin * plugin)
{
	cpl_recipe * recipe = (cpl_recipe *)plugin ;

	/* Create the parameters list in the cpl_recipe object */
	recipe->parameters = cpl_parameterlist_new() ;

	/* Fill the parameters list */

	return 0;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Execute the plugin instance given by the interface
  @param    plugin  the plugin
  @return   0 if everything is ok
 */
/*----------------------------------------------------------------------------*/
static int amber_raw_to_fitsimage_exec(cpl_plugin * plugin)
{
	cpl_recipe * recipe = (cpl_recipe *)plugin ;
	return amber_raw_to_fitsimage(recipe->parameters, recipe->frames) ;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Destroy what has been created by the 'create' function
  @param    plugin  the plugin
  @return   0 if everything is ok
 */
/*----------------------------------------------------------------------------*/
static int amber_raw_to_fitsimage_destroy(cpl_plugin * plugin)
{
	cpl_recipe  *   recipe = (cpl_recipe *)plugin ;
	cpl_parameterlist_delete(recipe->parameters) ;
	return 0 ;
}

/*----------------------------------------------------------------------------*/
/**
  @brief    Get the command line options and execute the data reduction
  @param    parlist     the parameters list
  @param    frameset   the frames list
  @return   0 if everything is ok
 */
/*----------------------------------------------------------------------------*/
static int amber_raw_to_fitsimage(
		cpl_parameterlist     *   parlist,
		cpl_frameset    *   frameset)
{
	cpl_frame        * cur_frame=NULL;
	cpl_frame        * pFrameProduct = NULL;
	cpl_imagelist    * pImagelist = NULL;
	char               szMessage[1024];
	cpl_frame        * pFrame = NULL;
	cpl_propertylist * pHeader = NULL;
    cpl_propertylist * qclist = NULL;
	int  iStatus = 0;
	const char * fctid = "amber_raw_to_fitsimage";
	int iNumbExt     = 0;  /* Number of extensions in FITS file */
	int iTelescopes  = 0;  /* Number of Telescopes used to produce raw data */
	//amdlibERROR_MSG  errMsg;
	int    pszTemp;
	char * pszInfile;
	char   szProduct[512];
	cpl_propertylist  *  pHeader_tmp = NULL;


	cpl_msg_info( fctid, "Start of DataReduction");

	/* For DFS fill Header function later */;
	/* pHeader = cpl_propertylist_new();   IMPLICIT to load later */
	pFrame  = cpl_frame_new();

	/* Outfile goes to temp */
	strcpy( szProduct, "/tmp/amber_display.fits" );

	/* Just use the first frame */
	cur_frame = cpl_frameset_get_position(frameset, 0);
	cpl_frame_set_group(cur_frame, CPL_FRAME_GROUP_RAW);
	pszInfile = (char *)cpl_frame_get_filename( cur_frame );


	{


		/* read the number of extensions from the file */
		iNumbExt = cpl_fits_count_extensions(pszInfile);
		/*      cpl_msg_info(cpl_func,"iNumbExt: %d", iNumbExt); */

		if( iNumbExt < 3 )
		{
			/* Necessary extension 2 and 3 is not existing! */
			iStatus = 2;
		}
		else
		{
			/* Decide 2 or 3 telescope case by number of subwindows */

			pHeader_tmp = cpl_propertylist_load(pszInfile,2);

			pszTemp=cpl_propertylist_get_int(pHeader_tmp,"NREGION");
			cpl_msg_info(cpl_func,"NREGION: %d", pszTemp);

			cpl_propertylist_delete(pHeader_tmp);

			if(pszTemp == 4){
				iTelescopes = 2;
			}
			else if( pszTemp == 5){
				iTelescopes = 3;
			}
			else if(pszTemp == 1){
				iTelescopes = 1;
			}
			if(iTelescopes != 1 && iTelescopes != 2 && iTelescopes != 3 )
			{
				iStatus = 3;
			}
			else
			{
				/* Load raw frame and store it as an image */
				if (amdlibLoadRawData(pszInfile, &rawData, errMsg) !=
						amdlibSUCCESS)
				{
#ifdef TL_DEBUG	    	
					printf ("Could not load raw data file '%s'\n", pszInfile);
					printf ("%s\n", errMsg);
#endif      
					iStatus = 20;
				}

				if( amdlibSaveRawDataToFits( szProduct, &rawData, errMsg) !=
						amdlibSUCCESS )
				{
#ifdef TL_DEBUG	      	
					printf ("Could not write image file '%s'\n", szProduct);
					printf ("%s\n", errMsg);
#endif      
					iStatus = 21;
				}
				else
				{
					/* OK */
					iStatus = 0;
					amdlibReleaseRawData(&rawData);
				}
			} /* wrong region count */
		} /* ext 2 not present */
	}



	/* Create the Product file, start with filling the header */

	sprintf( szMessage, "Extracted Header from file %s.", pszInfile );
	cpl_msg_info( fctid, "%s", szMessage );

	/* Create a set of frames with just this frame, so header will be correct */

	pImagelist = cpl_imagelist_load(szProduct, CPL_TYPE_FLOAT, 0 );

	pHeader = cpl_propertylist_load( pszInfile, 0 );

	pFrameProduct = cpl_frame_new();
	cpl_frame_set_filename( pFrameProduct, szProduct );
	cpl_frame_set_type    ( pFrameProduct, CPL_FRAME_TYPE_IMAGE );
	cpl_frame_set_tag     ( pFrameProduct, "AMBER_RAW_IMAGE" );
	cpl_frame_set_group   ( pFrameProduct, CPL_FRAME_GROUP_PRODUCT );
	cpl_frame_set_level   ( pFrameProduct, CPL_FRAME_LEVEL_FINAL );


	/* Add the necessary DFS fits header information to the product */
	if( cpl_dfs_setup_product_header(  pHeader,
			pFrameProduct,
			frameset,
			parlist,
			"amber_raw_to_fitsimage", /* const char *  recid,  */
			"AMBER", /* const char *  pipeline_id,  */
			"AMBER",  /* const char *  dictionary_id */
			NULL
	)  != CPL_ERROR_NONE )
	{
		/* Error */
		sprintf( szMessage, "Warning: problem with product header. [%s]",
				cpl_error_get_where() );

		cpl_msg_info( fctid, "%s", szMessage );
		/*     cpl_msg_info(cpl_func, cpl_error_get_message()); */
		iStatus = 16;
	}


    /* Add a QC parameter  */
    qclist = cpl_propertylist_new();

    cpl_image * ima_summ = cpl_imagelist_collapse_create(pImagelist);
    cpl_image_multiply_scalar(ima_summ, cpl_imagelist_get_size(pImagelist));

    /* Add the product category and save image */
    cpl_propertylist_update_string(qclist, CPL_DFS_PRO_CATG, "AMBER_RAW_SUM");

    cpl_dfs_save_image(frameset, NULL, parlist, frameset, NULL,
                    ima_summ, CPL_TYPE_FLOAT,
                    "amber_raw_to_fitsimage", qclist, NULL,
                    PACKAGE "/" PACKAGE_VERSION, "amber_raw_sum.fits");

    cpl_propertylist_update_string(qclist, CPL_DFS_PRO_CATG, "AMBER_RAW_CUBE");

    cpl_dfs_save_imagelist(frameset, NULL, parlist, frameset, NULL,
                    pImagelist, CPL_TYPE_FLOAT,
                    "amber_raw_to_fitsimage", qclist, NULL,
                    PACKAGE "/" PACKAGE_VERSION, "amber_raw_cube.fits");

    cpl_propertylist_delete(qclist);
    cpl_image_delete(ima_summ);


	cpl_frame_delete(pFrame);
	cpl_frame_delete(pFrameProduct);
	cpl_propertylist_delete(pHeader);

	cpl_imagelist_delete(pImagelist);

	/* FREE CPL STUFF !!! */

	/* ---------
  0  = OK
  1  = not a FITS file
  2  = Ext 2 or 3 not present
  3  = Wrong number of Regions in Extension 2 
  4  = No new FITS Header available
  5  = Cannot create outfile 

  11 = no memory for buffer
  12 = cannot open table with IMAGING_DATA

  20 = amdlib error
  ----------- */

	//sprintf ( szMessage, "Status: %d for %s", iStatus, szProduct );
	//cpl_msg_info( fctid, "%s", szMessage );

	//cpl_msg_info( fctid, "End of DataReduction");

	//cpl_error_reset();


	return iStatus;
}
