/*   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;
}
/**@}*/
