/*   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     *
 *                                                                           */

/*
 * $Author: amodigli $
 * $Date: 2013-10-11 12:44:02 $
 * $Revision: 1.25 $
 * $Name: not supported by cvs2svn $
 */

/*---------------------------------------------------------------------------*/
/**
 * @defgroup flames_crea_bp_ima
 *    This command creates a basic bad pixel mask to be used for subsequent
 *    processing of FLAMES/UVES data, based on tables of known CCD
 *    blemishes.
 */
/*---------------------------------------------------------------------------*/

/*-----------------------------------------------------------------------------
  Includes
  ---------------------------------------------------------------------------*/
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <flames_crea_bp_ima.h>

#include <flames_creamask.h>
#include <flames_dfs.h>

#include <uves_corrbadpix.h>
#include <uves_chip.h>
#include <uves_dfs.h>
#include <uves_pfits.h>
#include <uves_utils_wrappers.h>
#include <uves_error.h>
#include <flames_utils.h>

#include <float.h>
/*-----------------------------------------------------------------------------
  Defines
  ---------------------------------------------------------------------------*/
/**@{*/
/*-----------------------------------------------------------------------------
  Functions prototypes
  ---------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
  Implementation
  ---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/**
   @brief    Generates a bad pixel map
   @param    bad_ima           input image
   @param    ou_file            output filename
   @param    slevel            saturation threshold
   @param    chip              CCD chip
   @param    binx              x binning
   @parma    biny              y binning
   @return   bad pixel image filename

*/
/*---------------------------------------------------------------------------*/
void
flames_crea_bp_ima(const cpl_frame *in_ima, 
                   const char *ou_file,
		   int slevel,
		   enum uves_chip chip,
		   int binx, 
                   int biny,const cpl_table* ozpoz)
{
  cpl_frame *ou_frame=NULL;
  cpl_image *in_image = NULL;
  cpl_image *ou_image = NULL;

  cpl_table *trap = NULL;
  cpl_table *sp = NULL;

  int ** bp_map = NULL;
    

  const char * IN_A = cpl_frame_get_filename(in_ima);
  const char * IN_B = NULL; /*table filename with known trap locations */
  const char * IN_C = NULL; /*table filename with saturated pixels */

  const char * const IN_B_XS = "XSTARTPIX"; 
  const char * const IN_B_XE = "XENDPIX"; 
  const char * const IN_B_YS = "YSTARTPIX"; 
  const char * const IN_B_YE = "YENDPIX"; 

  const char * const IN_C_X_PIX = "X_PIX"; 
  const char * const IN_C_Y_PIX = "Y_PIX"; 

  const char * OUT_A = ou_file;

  cpl_mask *inside = NULL;
  int plane = 0;
  int extension = 0;
  int row, x, y, nx, ny;
  uves_propertylist* ou_header = NULL;
  bool red_ccd_is_new=false;

  IN_B = uves_sprintf("%s%s%s","trap_",uves_chip_tostring_lower(chip),".fits");
  IN_C = uves_sprintf("%s%s%s","sp_",uves_chip_tostring_lower(chip),".fits");

  assure_nomsg( in_ima != NULL, CPL_ERROR_NULL_INPUT );

  check( in_image = uves_load_image(in_ima,
				    plane,
				    extension,
				    &ou_header),
	 "Could not load image");
  check_nomsg(red_ccd_is_new=uves_ccd_is_new(ou_header));

  check( bp_map = uves_get_badpix(chip, binx, biny, true,red_ccd_is_new),
	 "Could not get bad pixel map");
    
  trap = cpl_table_new(1);

  cpl_table_new_column(trap, IN_B_XS, CPL_TYPE_DOUBLE); /* Low level code    */
  cpl_table_new_column(trap, IN_B_XE, CPL_TYPE_DOUBLE); /* wants type double */
  cpl_table_new_column(trap, IN_B_YS, CPL_TYPE_DOUBLE);
  cpl_table_new_column(trap, IN_B_YE, CPL_TYPE_DOUBLE);

  for (row = 0; bp_map[row][0] != -1; row++) {
    cpl_table_set_size(trap, row+1);
    cpl_table_set_double(trap, IN_B_XS, row, bp_map[row][0]);
    cpl_table_set_double(trap, IN_B_YS, row, bp_map[row][1]);
    cpl_table_set_double(trap, IN_B_XE, row, bp_map[row][2]);
    cpl_table_set_double(trap, IN_B_YE, row, bp_map[row][3]);
  }

  check( cpl_table_save(trap, 
			NULL, /* primay header */
			NULL, /* extension header */
			IN_B,
			CPL_IO_DEFAULT),
	 "Could not save table %s", IN_B);


  /* Finds all pixels outside interval [-oo, slevel] */

  inside = cpl_mask_threshold_image_create(in_image, -DBL_MAX, slevel);
  assure_mem( inside );

  sp = cpl_table_new(1);

  cpl_table_new_column(sp, IN_C_X_PIX, CPL_TYPE_DOUBLE); /* FLAMES C code expects */
  cpl_table_new_column(sp, IN_C_Y_PIX, CPL_TYPE_DOUBLE); /* type double, not int */
  cpl_table_new_column(sp, "VALUE", CPL_TYPE_DOUBLE);

  nx = cpl_image_get_size_x(in_image);
  ny = cpl_image_get_size_y(in_image);
  row = 0;
  for (y = 1; y <= ny; y++) {
    for(x = 1; x <= nx; x++) {
      if (cpl_mask_get(inside, x, y) == CPL_BINARY_0) {
	int pis_rejected;
	cpl_table_set_size(sp, row+1);
	cpl_table_set_double(sp, IN_C_X_PIX, row, x);
	cpl_table_set_double(sp, IN_C_Y_PIX, row, y);
	cpl_table_set_double(sp,"VALUE",row,
			     cpl_image_get(in_image, x, y, &pis_rejected));
	row++;
      }
    }
  }
  check( cpl_table_save(sp, 
			NULL, /* primay header */
			NULL, /* extension header */
			IN_C,
			CPL_IO_DEFAULT),
	 "Could not save table %s", IN_C);

  uves_msg_debug("Input hot image Name is: \t %s", IN_A);
  uves_msg_debug("Input trap col table Name is: \t %s", IN_B);
  uves_msg_debug("Trap Start X: \t %s", IN_B_XS);
  uves_msg_debug("Trap End   X: \t %s", IN_B_XE);
  uves_msg_debug("Trap Start Y: \t %s", IN_B_YS);
  uves_msg_debug("Trap End   Y: \t %s", IN_B_YE);

  uves_msg_debug("Input sat pix table: \t %s", IN_C);
  uves_msg_debug("Input sat pix tab X: \t %s", IN_C_X_PIX);
  uves_msg_debug("Input sat pix tab Y: \t %s", IN_C_Y_PIX);
  uves_msg_debug("Input sat trshold Y: \t %d", slevel);

  uves_msg_debug("Output hot pix image: \t %s", OUT_A);

  assure( flames_creamask(IN_A,
			  IN_B,
			  IN_C,
			  OUT_A,
			  IN_B_XS,
			  IN_B_XE,
			  IN_B_YS,
			  IN_B_YE,
			  IN_C_X_PIX,
			  IN_C_Y_PIX) == 0,
	  CPL_ERROR_ILLEGAL_OUTPUT,
	  "Could not create bad pixel mask");

  check_nomsg( ou_image = cpl_image_load(OUT_A, CPL_TYPE_INT, 0, 0) );
  
  ou_frame = cpl_frame_new();
  cpl_frame_set_filename(ou_frame, OUT_A);
  cpl_frame_set_type(ou_frame, CPL_FRAME_TYPE_IMAGE);

  flames_dfs_write_descr(ou_header, chip, false,ozpoz);
  check_nomsg( uves_save_image( ou_image, ou_file, ou_header, true, true) );
    
 cleanup:
  uves_free_string_const(&IN_B);
  uves_free_string_const(&IN_C);

  uves_free_frame(&ou_frame);
  uves_free_image(&ou_image);
  uves_free_propertylist(&ou_header);
  uves_badmap_free(&bp_map);
  uves_free_image(&in_image);
  uves_free_table(&trap);
  uves_free_table(&sp);
  uves_free_mask(&inside);
  return;
}
/**@}*/
