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


}



/**@}*/
