/* $Id: flames_utl_unpack.c,v 1.7 2010-09-24 09:30:44 amodigli Exp $
 *
 * This file is part of the UVES 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: amodigli $
 * $Date: 2010-09-24 09:30:44 $
 * $Revision: 1.7 $
 * $Name: not supported by cvs2svn $
 */

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

/*-----------------------------------------------------------------------------
                                Includes
 ----------------------------------------------------------------------------*/
#include <string.h>

/* cpl */
#include <cpl.h>

/* irplib */
#include <irplib_utils.h>
/*
#include <uves_tpl_utils.h>
#include <uves_key_names.h>
#include <uves_pro_types.h>
#include <uves_functions.h>
*/

#include <flames_utils_science.h>
#include <flames_utils.h>
#include <uves_dfs.h>
#include <flames_dfs.h>
#include <uves_chip.h>
#include <uves_pfits.h>
#include <uves_msg.h>
#include <uves_error.h>
#include <uves_utils_wrappers.h>

#define recipe_id "flames_utl_unpack"

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

static int flames_utl_unpack_create(cpl_plugin *) ;
static int flames_utl_unpack_exec(cpl_plugin *) ;
static int flames_utl_unpack_destroy(cpl_plugin *) ;
static int flames_utl_unpack(cpl_parameterlist *, cpl_frameset *) ;


static cpl_error_code
flames_unpack_spectra_from_image(cpl_frame* frm,
                              cpl_parameterlist   *   parameters,
                               cpl_frameset* set);
static cpl_error_code
flames_unpack_image_from_cube(cpl_frame* frm,
                              cpl_parameterlist   *   parameters,
                               cpl_frameset* set);

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

static char flames_utl_unpack_description[] =
"This recipe unpack flames-uves packed products.\n"
"Information on relevant parameters can be found with\n"
"esorex --params flames_utl_unpack\n"
"esorex --help flames_utl_unpack\n"
"\n";

/*-----------------------------------------------------------------------------
                                Functions code
 ----------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/**
 * @defgroup flames_utl_unpack  Recipe to unpack frames
 */
/*---------------------------------------------------------------------------*/

/**@{*/
/*---------------------------------------------------------------------------*/
/**
  @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,
                    UVES_BINARY_VERSION,
                    CPL_PLUGIN_TYPE_RECIPE,
                    "flames_utl_unpack",
                    "Unpack flames-uves packed frames",
                    flames_utl_unpack_description,
                    "Andrea Modigliani",
                    "Andrea.Modigliani@eso.org",
                    uves_get_license(),
                    flames_utl_unpack_create,
                    flames_utl_unpack_exec,
                    flames_utl_unpack_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 flames_utl_unpack_create(cpl_plugin * plugin)
{
    cpl_recipe      * recipe ;

    /* Get the recipe out of the plugin */
    if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
        recipe = (cpl_recipe *)plugin ;
    else return -1 ;
    cpl_error_reset();
    irplib_reset();

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

    /* Fill the parameters list */
    /* --stropt */
 
    /* Return */
    return 0;
}

/*---------------------------------------------------------------------------*/
/**
  @brief    Execute the plugin instance given by the interface
  @param    plugin  the plugin
  @return   0 if everything is ok
 */
/*---------------------------------------------------------------------------*/
static int flames_utl_unpack_exec(cpl_plugin * plugin)
{
    cpl_recipe  *   recipe ;
     int code=0;
     cpl_errorstate initial_errorstate = cpl_errorstate_get();

    /* Get the recipe out of the plugin */
    if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
        recipe = (cpl_recipe *)plugin ;
    else return -1 ;
    cpl_error_reset();
    irplib_reset();
    code = flames_utl_unpack(recipe->parameters, recipe->frames) ;


    if (!cpl_errorstate_is_equal(initial_errorstate)) {                      
        /* Dump the error history since recipe execution start.                
           At this point the recipe cannot recover from the error */           
        cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);              
    } 

    return code ;
}

/*---------------------------------------------------------------------------*/
/**
  @brief    Destroy what has been created by the 'create' function
  @param    plugin  the plugin
  @return   0 if everything is ok
 */
/*---------------------------------------------------------------------------*/
static int flames_utl_unpack_destroy(cpl_plugin * plugin)
{
    cpl_recipe  *   recipe ;
    
    /* Get the recipe out of the plugin */
    if (cpl_plugin_get_type(plugin) == CPL_PLUGIN_TYPE_RECIPE) 
        recipe = (cpl_recipe *)plugin ;
    else return -1 ;

    cpl_parameterlist_delete(recipe->parameters) ; 
    return 0 ;
}

/*---------------------------------------------------------------------------*/
/**
  @brief    Get the command line options and execute the data reduction
  @param    parlist     the parameters list
  @param    framelist   the frames list
  @return   0 if everything is ok
 */
/*---------------------------------------------------------------------------*/
static int 
flames_utl_unpack( cpl_parameterlist   *   parlist, 
        cpl_frameset        *   set)
{   
    uves_propertylist    *   plist=NULL ;
    int n=0;
    int i=0;
    int naxis=0;
    cpl_frame* frm=NULL;
    const char* tag=NULL;
    const char* name=NULL;
    
          uves_msg("Welcome to UVES Pipeline release %d.%d.%d",
        UVES_MAJOR_VERSION,UVES_MINOR_VERSION,UVES_MICRO_VERSION);

    /* HOW TO RETRIEVE INPUT PARAMETERS */
    /* --stropt */
   
    /* Identify the RAW and CALIB frames in the input frameset */
    //check(uves_dfs_set_groups(set),
    //     "Cannot identify RAW and CALIB frames") ;
 
    /* HOW TO ACCESS INPUT DATA */
    n=cpl_frameset_get_size(set);
    if(n<1) {
      uves_msg_error("Empty input frame list!");
      goto cleanup ;
    }

    for(i=0;i<n;i++) {
      check_nomsg(frm=cpl_frameset_get_frame(set,i));
      check_nomsg(tag=cpl_frame_get_tag(frm));
      check_nomsg(name=cpl_frame_get_filename(frm));
      check_nomsg(plist=uves_propertylist_load(name,0));
      check_nomsg(naxis=uves_pfits_get_naxis(plist));
      //uves_msg("name=%s",name);
      if(naxis==3) {
        check_nomsg(flames_unpack_image_from_cube(frm,parlist,set));
      } else if (naxis==2) {
	check_nomsg(flames_unpack_spectra_from_image(frm,parlist,set));
      } else {

      }

      uves_free_propertylist(&plist);
    }


 cleanup:
   

    if (cpl_error_get_code()) {
        return -1 ;
    } else {
        return 0 ;
    }

}


static cpl_error_code
flames_unpack_image_from_cube(cpl_frame* frm,
                              cpl_parameterlist   *   parameters,
                              cpl_frameset* set)
{

  const char* name=NULL;
  const char* fname=NULL;
  const char* tag=NULL;
  uves_propertylist* href=NULL;
  uves_propertylist* hout=NULL;
  cpl_imagelist* iml=NULL;
  int size=0;
  int i=0;
  cpl_frame* frame=NULL;
  cpl_image* img=NULL;

  cknull_nomsg(parameters);
  check_nomsg(name=cpl_frame_get_filename(frm));
  check_nomsg(tag=cpl_frame_get_tag(frm));
  check_nomsg(href=uves_propertylist_load(name,0));
  check_nomsg(hout=uves_propertylist_duplicate(href));

  check_nomsg(iml=cpl_imagelist_load(name,CPL_TYPE_FLOAT,0));
  check_nomsg(size=cpl_imagelist_get_size(iml));
  for(i=0;i<size;i++) {
    frame=cpl_frame_new();
    check_nomsg(img=cpl_imagelist_get(iml,i));
    check_nomsg(fname=uves_sprintf("slic_%d_%s",i,flames_get_basename(name)));
    check_nomsg( uves_save_image(img,fname,hout,true, true) );

    check_nomsg(cpl_frame_set_filename(frame, fname)) ;
    check_nomsg(cpl_frame_set_tag(frame, tag)) ;
    check_nomsg(cpl_frame_set_type(frame, CPL_FRAME_TYPE_IMAGE)) ;
    check_nomsg(cpl_frame_set_group(frame, CPL_FRAME_GROUP_PRODUCT)) ;
    check(cpl_frame_set_level(frame, CPL_FRAME_LEVEL_FINAL),
      "Error while initialising the product frame") ;

    cpl_frameset_insert(set,frame);
    /*
    check_nomsg(cpl_propertylist_erase_regexp(hout, "^ESO PRO CATG",0));
    check(cpl_dfs_setup_product_header(hout, 
                                       frame, 
                                       set, 
                                       parameters,
                                       "flames_utl_unpack", 
                                       PACKAGE "/" PACKAGE_VERSION, 
                                       "PRO-1.15"),
      "Problem in the product DFS-compliance") ;

    check( flames_frameset_insert(
				set,
				CPL_FRAME_GROUP_PRODUCT,
				CPL_FRAME_TYPE_IMAGE,
				CPL_FRAME_LEVEL_INTERMEDIATE,
				fname,
				tag,
				hout,
				parameters,
				recipe_id,
				PACKAGE "/" PACKAGE_VERSION,
				NULL, NULL, true, 0),
	 "Could not add image %s (%s) to frameset",
	 fname, tag);
    */

  }


 cleanup:
  uves_free_propertylist(&href);
  uves_free_propertylist(&hout);
  uves_free_imagelist(&iml);


  return cpl_error_get_code() ;

}



static cpl_error_code
flames_unpack_spectra_from_image(cpl_frame* frm,
                               cpl_parameterlist   *   parameters,
                               cpl_frameset* set)
{



  const char* name=NULL;
  const char* fname=NULL;
  const char* tag=NULL;
  cpl_propertylist* href=NULL;
  cpl_propertylist* hout=NULL;
  cpl_image* ima=NULL;

  int i=0;
  cpl_frame* frame=NULL;
  cpl_image* img=NULL;
  int sx=0;
  int sy=0;

  cknull_nomsg(parameters);
  check_nomsg(name=cpl_frame_get_filename(frm));
  check_nomsg(tag=cpl_frame_get_tag(frm));
  check_nomsg(href=cpl_propertylist_load(name,0));
  check_nomsg(hout=cpl_propertylist_duplicate(href));
  check_nomsg(uves_sanitise_propertylist(hout));

  check_nomsg(ima=cpl_image_load(name,CPL_TYPE_FLOAT,0,0));
  check_nomsg(sx=cpl_image_get_size_x(ima));
  check_nomsg(sy=cpl_image_get_size_y(ima));

  for(i=0;i<sy;i++) {
    frame=cpl_frame_new();
    //img=cpl_image_new(sx,1,CPL_TYPE_FLOAT);
    check_nomsg(img=cpl_image_extract(ima,1,i+1,sx,i+1));
    check_nomsg(fname=uves_sprintf("slic_%d_%s",i,flames_get_basename(name)));
    cpl_image_save(img,fname,CPL_BPP_IEEE_FLOAT,hout,CPL_IO_DEFAULT);
    //uves_msg("i=%d tag=%s name=%s",i,tag,name);
 



    check_nomsg(cpl_frame_set_filename(frame, fname)) ;
    check_nomsg(cpl_frame_set_tag(frame, tag)) ;
    check_nomsg(cpl_frame_set_type(frame, CPL_FRAME_TYPE_IMAGE)) ;
    check_nomsg(cpl_frame_set_group(frame, CPL_FRAME_GROUP_PRODUCT)) ;
    check(cpl_frame_set_level(frame, CPL_FRAME_LEVEL_FINAL),
      "Error while initialising the product frame") ;
    cpl_frameset_insert(set,frame);
    
    /*
    check_nomsg(cpl_propertylist_erase_regexp(hout, "^ESO PRO CATG",0));
    check(cpl_dfs_setup_product_header(hout, 
                                       frame, 
                                       set, 
                                       parameters,
                                       "flames_utl_unpack", 
                                       PACKAGE "/" PACKAGE_VERSION, 
                                       "PRO-1.15"),
      "Problem in the product DFS-compliance") ;
   
   
    check( flames_frameset_insert(
				set,
				CPL_FRAME_GROUP_PRODUCT,
				CPL_FRAME_TYPE_IMAGE,
				CPL_FRAME_LEVEL_INTERMEDIATE,
				fname,
				tag,
				hout,
				parameters,
			        "pippo",
				PACKAGE "/" PACKAGE_VERSION,
				NULL, NULL, true, 0),
	 "Could not add image %s (%s) to frameset",
	 fname, tag);
    
    */
  uves_free_image(&img);

  }


 cleanup:
  cpl_propertylist_delete(href);
  cpl_propertylist_delete(hout);
  uves_free_image(&ima);
  uves_free_image(&img);

  return cpl_error_get_code() ;


}




/**@}*/
