/*
 * This file is part of the ESO SINFONI Pipeline
 * Copyright (C) 2004,2005 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, 51 Franklin St, Fifth Floor, Boston, MA  02111-1307  USA
 */
/*----------------------------------------------------------------------------

   File name    :       sinfo_new_add_bp_map.c
   Author       :    A. Modigliani
   Created on   :    Oct 13, 2004
   Description  :    Coadd different BP MAP 

 ---------------------------------------------------------------------------*/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif
/*----------------------------------------------------------------------------
                                Includes
 ---------------------------------------------------------------------------*/
#include "sinfo_new_add_bp_map.h"
#include "sinfo_pro_save.h"
#include "sinfo_error.h"
#include "sinfo_utils_wrappers.h"
/* #include "image_ops.h" */
#include "sinfo_pro_types.h"
#include "sinfo_functions.h"
#include "sinfo_detlin.h"
/*----------------------------------------------------------------------------
                                Prototypes
 ---------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------
                                Defines
 ---------------------------------------------------------------------------*/


/*----------------------------------------------------------------------------
  Function Definitions
  ---------------------------------------------------------------------------*/
/**@{*/
/**
 * @addtogroup sinfo_bad_pix_search Bad Pixel Search
 *
 * TBD
 */


/**
   @brief coadd bad pixel maps
   @name sinfo_new_add_bp_map()
   @param plugin_id name of plug-in
   @param config    recipe configuration parameters
   @param sof       set of frame
   @return integer (0 if it worked, -1 if it doesn't)  
 */

int 
sinfo_new_add_bp_map (const char* plugin_id,
                      cpl_parameterlist* config, 
                      cpl_frameset* sof,cpl_frameset* ref_set)
{

    int  nmsk =0;
    int  nmsk_ref_fits =0;
    int i=0;
    int k=0;
    int n_bad=0;
    cpl_image**  img_sum=NULL;
    cpl_image*   img_set=NULL;
    cpl_image*   img_tot=NULL;
    cpl_frameset* msk_set=NULL;
    cpl_frameset* msk_ref_fits=NULL;
    cpl_frame* frame=NULL;
    double max=0;
    char frame_name[FILE_NAME_SZ];
    char out_msk[FILE_NAME_SZ];

    cpl_table* qclog_tbl=NULL;
    char * tag=NULL;
    char * tmp_tag=NULL;

    strcpy(out_msk, MASTER_BPMAP_OUT_FILENAME);


    /* cpl_parameterlist_dump(config); */
    check_nomsg(msk_set=cpl_frameset_new());
    ck0_nomsg(sinfo_contains_frames_kind(sof,msk_set,"BP_MAP"));
    check_nomsg(nmsk = cpl_frameset_get_size(msk_set));
    if(nmsk == 0) {
        sinfo_msg_warning("No bad pixel masks to add");
        goto cleanup;
    }


    check_nomsg(frame = cpl_frameset_get_frame(msk_set,0));
    strcpy(frame_name,cpl_frame_get_filename(frame));
    check_nomsg(tag = (char*) cpl_frame_get_tag(frame));
    {
        check_nomsg(msk_ref_fits=cpl_frameset_new());
        if (nmsk < 1) {
            sinfo_msg_error("No input frames. Nothing to do.");
            goto cleanup;
        } else if (nmsk==1) {

            sinfo_msg_warning("Only one input frames. Use it as master.");
            check_nomsg(frame = cpl_frameset_get_frame(msk_set,0));
            strcpy(frame_name,cpl_frame_get_filename(frame));
            check_nomsg(tag = (char*) cpl_frame_get_tag(frame));

        } else {

            ck0_nomsg(sinfo_contains_frames_kind(msk_set,
                            msk_ref_fits,PRO_BP_MAP_NO));
            check_nomsg(nmsk_ref_fits = cpl_frameset_get_size(msk_ref_fits));

            if (nmsk_ref_fits < 1) {
                sinfo_msg_warning("No %s input frames. Uses %s for FITS header",
                                PRO_BP_MAP_NO,PRO_BP_MAP_DI);

                ck0_nomsg(sinfo_contains_frames_kind(msk_set,
                                msk_ref_fits,PRO_BP_MAP_DI));
                check_nomsg(nmsk_ref_fits = cpl_frameset_get_size(msk_ref_fits));


                if (nmsk_ref_fits < 1) {

                    sinfo_msg_warning("No %s input frames. Uses %s for FITS header",
                                    PRO_BP_MAP_DI,PRO_BP_MAP_NL);

                    ck0_nomsg(sinfo_contains_frames_kind(msk_set,
                                    msk_ref_fits,PRO_BP_MAP_NL));
                    check_nomsg(nmsk_ref_fits = cpl_frameset_get_size(msk_ref_fits));

                    if (nmsk_ref_fits < 1) {

                        sinfo_msg_warning("No %s input frames. Uses 1st mask in the list",
                                        PRO_BP_MAP_NL);
                        sinfo_free_frameset(&msk_ref_fits);
                        check_nomsg(msk_ref_fits=cpl_frameset_duplicate(msk_set));
                        check_nomsg(frame = cpl_frameset_get_frame(msk_set,0));
                        check_nomsg(cpl_frameset_erase_frame(msk_set,frame));
                        check_nomsg(tag = (char*) cpl_frame_get_tag(frame));

                    } else {
                        sinfo_msg("Uses as reference frame %s",PRO_BP_MAP_NL);
                        check_nomsg(frame = cpl_frameset_get_frame(msk_ref_fits,0));
                        strcpy(frame_name,cpl_frame_get_filename(frame));
                        tag = (char*) PRO_BP_MAP_NL;
                    }
                } else {
                    sinfo_msg("Uses as reference frame %s",PRO_BP_MAP_DI);
                    check_nomsg(frame = cpl_frameset_get_frame(msk_ref_fits,0));
                    strcpy(frame_name,cpl_frame_get_filename(frame));
                    tag = (char*) PRO_BP_MAP_DI;
                }
            } else {
                sinfo_msg("Uses as reference frame %s",PRO_BP_MAP_NO);
                check_nomsg(frame = cpl_frameset_get_frame(msk_ref_fits,0));
                strcpy(frame_name,cpl_frame_get_filename(frame));
                tag = (char*) PRO_BP_MAP_NO;
            }
        }

        check_nomsg(nmsk = cpl_frameset_get_size(msk_set));
        cknull_nomsg(img_sum = (cpl_image**) cpl_calloc ((nmsk+1),
                        sizeof(cpl_image*))) ;
        cknull_nomsg(img_sum[0]=cpl_image_load(frame_name,CPL_TYPE_FLOAT,0,0));

        /* here mem leak */
        for (i=0;i<nmsk;i++) {
            check_nomsg(frame = cpl_frameset_get_frame(msk_set,i));
            check_nomsg(strcpy(frame_name,cpl_frame_get_filename(frame)));
            check_nomsg(tmp_tag=(char*)cpl_frame_get_tag(frame));

            if(strcmp(tmp_tag,tag) == 0 ) {
                cknull_nomsg(img_set=cpl_image_load(frame_name,CPL_TYPE_FLOAT,0,0));
                check_nomsg(max=cpl_image_get_max(img_set));
                if((strcmp(tmp_tag,PRO_BP_MAP_NL) == 0) && max>1 ) {
                    sinfo_msg("corr1");
                    check_nomsg(cpl_image_threshold(img_set,0.5,0.9,1,0));
                    sinfo_free_image(&(img_sum[0]));
                    check_nomsg(img_sum[0]=cpl_image_duplicate(img_set));
                }

            } else {

                cknull_nomsg(img_set=cpl_image_load(frame_name,CPL_TYPE_FLOAT,0,0));
                check_nomsg(max=cpl_image_get_max(img_set));
                if((strcmp(tmp_tag,PRO_BP_MAP_NL) == 0) &&  max>1 ) {
                    sinfo_msg("corr2 name=%s tag=%s",frame_name,tmp_tag);
                    check_nomsg(cpl_image_threshold(img_set,0.5,0.9,1,0));
                }

                cknull_nomsg(img_sum[k+1]=sinfo_new_combine_masks (img_sum[k], img_set));
                k++;
                sinfo_free_image(&img_set);
                sinfo_free_image(&(img_sum[k-1]));
            }
        }
        img_tot=cpl_image_duplicate(img_sum[k]);
        sinfo_free_image(&(img_sum[k]));
        sinfo_free_array_image(&img_sum);
        /*

    frame = cpl_frameset_get_frame(msk_set,0);
    strcpy(frame_name,cpl_frame_get_filename(frame));
    img_sum=cpl_image_load(frame_name,CPL_TYPE_INT,0,0);

    for (i=1;i<nmsk;i++) {
    frame = cpl_frameset_get_frame(msk_set,i);
    strcpy(frame_name,cpl_frame_get_filename(frame));
    img_set=cpl_image_load(frame_name,CPL_TYPE_INT,0,0);
    cpl_mask_and(img_sum, img_set);

    }

         */

        n_bad = sinfo_new_count_bad_pixels(img_tot) ;
        sinfo_msg ("number of bad pixels: %d\n", n_bad) ;
        cknull_nomsg(qclog_tbl = sinfo_qclog_init());
        ck0_nomsg(sinfo_qclog_add_int(qclog_tbl,"QC MBP_MAP NBADPIX",
                        n_bad,"No of bad pixels","%d"));

        if (nmsk>1) {
            ck0(sinfo_pro_save_ima(img_tot,ref_set,sof,out_msk,
                            PRO_MASTER_BP_MAP,qclog_tbl,
                            plugin_id,config),
                            "cannot save ima %s", out_msk);

        } else {
            ck0(sinfo_pro_save_ima(img_tot,ref_set,sof,out_msk,
                            PRO_MASTER_BP_MAP,qclog_tbl,
                            plugin_id,config),
                            "cannot save ima %s", out_msk);
        }

        sinfo_free_image(&img_tot);
        sinfo_free_table(&qclog_tbl);
        sinfo_free_frameset(&msk_ref_fits);
        sinfo_free_frameset(&msk_set);

    }

    cleanup:

    sinfo_free_image(&img_tot);
    if(img_sum!=NULL) {
        for(i=0;i<nmsk;i++) {
            if(img_sum[i] != NULL) {
                sinfo_free_image(&(img_sum[i]));
                img_sum[i]=NULL;
            }
        }
        sinfo_free_array_image(&img_sum);
        img_sum=NULL;
    }
    sinfo_free_image(&img_set);
    sinfo_free_table(&qclog_tbl);
    sinfo_free_frameset(&msk_set);
    sinfo_free_frameset(&msk_ref_fits);

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


}



/**@}*/
