/*                                                                           *
 *   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:11:42 $
 * $Revision: 1.45 $
 * $Name: not supported by cvs2svn $
 */

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

/*---------------------------------------------------------------------------*/
/**
 * @defgroup xsh_drl Handle Frames in PRE Format (xsh_prepare)
 * @ingroup drl_functions
 *
 * Prepare
 * This module is a template DRL function which adds the master
 * bias to the input frame
 */
/*---------------------------------------------------------------------------*/
/**@{*/

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

#include <xsh_drl.h>
#include <xsh_data_pre.h>
#include <xsh_data_instrument.h>
#include <xsh_dfs.h>
#include <xsh_pfits.h>
#include <xsh_error.h>
#include <xsh_msg.h>
#include <cpl.h>

/*----------------------------------------------------------------------------
                            Typedefs
  ---------------------------------------------------------------------------*/

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


/*----------------------------------------------------------------------------
                              Implementation
  ---------------------------------------------------------------------------*/

/**
  @brief 
    This function transform a BP map from raw to pre format

  @param[in] bpmap
    A bad pixel map in RAW format
  @param[in] bpmap     
    The default bad pixel map or NULL if not
  @return the frame corresponding to the map in PRE format.

*/
cpl_frame*
xsh_bpmap_2pre(cpl_frame* bpmap,const char* prefix, xsh_instrument* inst)
{
   cpl_frame* result=NULL;
   xsh_pre* pre=NULL;
   char* tag=NULL;
   char* name=NULL;

   pre= xsh_pre_create(bpmap,NULL,NULL,inst,0,false);
   tag=cpl_sprintf("%s_%s",prefix,xsh_instrument_arm_tostring(inst));
   name=cpl_sprintf("%s.fits",tag);
   
   if(strstr(tag,XSH_BP_MAP_NL)!=NULL) {
        xsh_bpmap_bitwise_to_flag(pre->data,QFLAG_NON_LINEAR_PIXEL);
   }
   result=xsh_pre_save(pre,name,tag,1 );
 
   xsh_pre_free(&pre);
   XSH_FREE(tag);
   XSH_FREE(name);
   return result;
}
/*---------------------------------------------------------------------------*/
/**
  @brief 
    This function transform RAW frames dataset in PRE frames dataset
    attaching the default bad pixel map and an error image.

  @param[in] frames
    A set of RAW frames
  @param[in] bpmap     
    The default bad pixel map or NULL if not
  @param[in] mbias 
    The master bias frame to compute ERRS in PRE files or NULL if not
  @param[in] prefix 
    The prefix of the resulting file name
  @param[in] instr 
    Instrument containing the arm , mode and lamp in use
  @param[in] pre_overscan_corr switch to use overscan region for bias estimation

*/
/*---------------------------------------------------------------------------*/
void xsh_prepare( cpl_frameset* frames, cpl_frame * bpmap, 
		  cpl_frame* mbias, const char* prefix, xsh_instrument* instr,
		  const int pre_overscan_corr,const bool flag_neg_and_thresh_pix)
{
  xsh_pre* pre = NULL;
  cpl_frame *current = NULL;
  cpl_frame* product = NULL;
  xsh_pre* bias = NULL;
  cpl_image* bias_data = NULL; 
  char result_name[256];
  char result_tag[256];
  int i,size;

  /* check input parameters */
  XSH_ASSURE_NOT_NULL( frames);
  XSH_ASSURE_NOT_NULL( prefix);
  XSH_ASSURE_NOT_NULL( instr);

  check( size = cpl_frameset_get_size( frames) );

  // Special for unitary tests (without master bias frame)
  if ( mbias == (cpl_frame *)-1 ) {
    bias_data = (cpl_image *)-1 ;
  }
  else if ( mbias != NULL ) {
    /* load data */
    check( bias = xsh_pre_load( mbias, instr));
    check( bias_data = xsh_pre_get_data( bias));
  } else  if ( mbias == NULL ) {
    bias_data = (cpl_image *)-1 ;
  }
  for( i=0; i<size; i++ ) {

    check( current = cpl_frameset_get_frame( frames, i));

    xsh_msg_dbg_medium("Load frame %s", cpl_frame_get_filename( current));

    check( pre = xsh_pre_create( current, bpmap, bias_data, instr,
				 pre_overscan_corr,flag_neg_and_thresh_pix));

    /* save result */
    if(strcmp(prefix,XSH_FLAT)==0) {
    	if(xsh_instrument_get_lamp(instr)==XSH_LAMP_QTH) {
    	   sprintf( result_name, "%s_QTH_PRE_%d.fits", prefix, i);
    	} else if(xsh_instrument_get_lamp(instr)==XSH_LAMP_D2) {
    	   sprintf( result_name, "%s_D2_PRE_%d.fits", prefix, i);
    	} else {
    	   sprintf( result_name, "%s_PRE_%d.fits", prefix, i);
    	}
    } else {
       sprintf( result_name, "%s_PRE_%d.fits", prefix, i);
    }
    sprintf( result_tag, "%s_PRE_%d", prefix, i);
    xsh_msg_dbg_medium( "Save frame %s", result_name);

    check( product = xsh_pre_save( pre, result_name,result_tag,1 ));
    xsh_pre_free( &pre);
    /* update the frame */
    check( cpl_frame_set_filename( current, 
      cpl_frame_get_filename( product) ) );
    check( cpl_frame_set_type( current,
      cpl_frame_get_type( product)));
    check( cpl_frame_set_level( current,
      cpl_frame_get_level( product)));
    xsh_free_frame( &product);
  }

  cleanup:
    if( cpl_error_get_code() != CPL_ERROR_NONE) {
      xsh_pre_free( &pre);
      xsh_free_frame( &product);
    }
    xsh_pre_free( &bias);
    return;
}

/*---------------------------------------------------------------------------*/
/**
  @brief 
    This function create a sub frame from PRE frame. the sub frame is 
    described by a box.

  @param[in] frame
    A pre frame
  @param[in] xmin    
    The x coordinate of the low-left corner of the box
  @param[in] ymin
    The y coordinate of the low-left corner of the box
  @param[in] xmax    
    The x coordinate of the up-right corner of the box
  @param[in] ymax
    The y coordinate of the up-right corner of the box
  @param[in] name
    The name of the sub frame
  @param[in] instr 
    Instrument containing the arm , mode and lamp in use

*/
/*---------------------------------------------------------------------------*/
cpl_frame * xsh_preframe_extract( cpl_frame* frame, int xmin, int ymin, 
  int xmax, int ymax, const char* name, xsh_instrument *instr)
{
  xsh_pre *pre = NULL;
  cpl_frame *result = NULL;
  const char* tag = NULL;

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

  check( tag = cpl_frame_get_tag( frame));
  check( pre = xsh_pre_load( frame, instr));
  check( xsh_pre_extract( pre, xmin , ymin, xmax, ymax));
  check( result = xsh_pre_save( pre, name, tag, 1));
  check( cpl_frame_set_tag( result, tag));
 
  cleanup:
    if( cpl_error_get_code() != CPL_ERROR_NONE) {
      xsh_free_frame( &result);
    }
    xsh_pre_free( &pre);
    return result;
}
/**@}*/
