/*                                                                           *
 *   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-06-12 12:22:16 $
 * $Revision: 1.1 $
 * $Name: not supported by cvs2svn $
 */

#include <xsh_utils_wrappers.h>
#include <xsh_utils_image.h>
#include <xsh_error.h>
#include <xsh_utils.h>
#include <xsh_pfits_qc.h>
#include <xsh_pfits.h>
#include <xsh_dfs.h>
#include <xsh_data_pre.h>
#include <xsh_data_instrument.h>
#include <math.h>
#include <string.h>
#include <float.h>
#include <xsh_globals.h>

/**
 * @brief    Compute median on imagelist
 * @param    in    input imagelist
 * @return   image containing median of input imagelist ingoring bad pixels
 */
cpl_image*
xsh_imagelist_collapse_median_create(cpl_imagelist* iml)
{

   int sx=0;
   int sy=0;
   int nimg=0;
   cpl_image* img=NULL;
   cpl_array* values=NULL;

   float **pdata = NULL;
   cpl_binary ** pbinary = NULL;

   int i=0;
   cpl_size k=0;
   int count=0;
   int sx_sy=0;

   float* pima=NULL;

   cpl_image* result=NULL;


   XSH_ASSURE_NOT_NULL_MSG(iml, "Null input imagelist");

   nimg=cpl_imagelist_get_size(iml);
   if(nimg>0) {
      img=cpl_imagelist_get(iml,0);
   }
   sx=cpl_image_get_size_x(img);
   sy=cpl_image_get_size_y(img);
   sx_sy=sx*sy;


   /* create the array of pointers to image data */
   pdata = cpl_malloc (nimg * sizeof (float *));
   assure (pdata != NULL, cpl_error_get_code (),
           "Cant allocate memory for data pointers");

   /* create the array of pointers to image binary */
   pbinary = cpl_malloc (nimg * sizeof (cpl_binary *));
   assure (pbinary != NULL, cpl_error_get_code (),
           "Cant allocate memory for binary pointers");

   /* Populate images pointer array */
   for (k = 0; k < nimg; k++) {
      check( pdata[k] = cpl_image_get_data_float(cpl_imagelist_get (iml, k)));
      check( pbinary[k] = cpl_mask_get_data(cpl_image_get_bpm(
                                               cpl_imagelist_get(iml, k))));
   }

   result=cpl_image_new(sx,sy,CPL_TYPE_FLOAT);
   pima=cpl_image_get_data_float(result);


   values=cpl_array_new(nimg,CPL_TYPE_FLOAT);

  /* Loop over all pixels */
  for (i = 0; i < sx_sy; i++){

     /* fill array only with good pixel values */
     for (count=0, k = 0; k < nimg; k++) {
        if ( ( (pbinary[k])[i] == CPL_BINARY_0) ) {
           cpl_array_set_float(values,k,(pdata[k])[i]);
           count++;
        } else {
           cpl_array_set_invalid(values,k);
        }

     } 
     /* finally compute median and store result in output */
     if(count>0) {
       pima[i]=cpl_array_get_median(values);
     } else {
        pima[i]=(pdata[0])[i];
     }
     
  }



  cleanup:

  cpl_array_delete(values);
  cpl_free(pdata);
  cpl_free(pbinary);

  return result;

}



/**
 * @brief    Compute mean on imagelist
 * @param    in    input imagelist
 * @return   image containing median of input imagelist ingoring bad pixels
 */
cpl_image*
xsh_imagelist_collapse_mean_create(cpl_imagelist* iml)
{

   int sx=0;
   int sy=0;
   int nimg=0;
   cpl_image* img=NULL;
   cpl_array* values=NULL;

   float **pdata = NULL;
   cpl_binary ** pbinary = NULL;

   int i=0;
   cpl_size k=0;
   int count=0;
   int sx_sy=0;
 
   float* pima=NULL;
   double mean=0;
   cpl_image* result=NULL;
 

   XSH_ASSURE_NOT_NULL_MSG(iml, "Null input imagelist");

   nimg=cpl_imagelist_get_size(iml);
   if(nimg>0) {
      img=cpl_imagelist_get(iml,0);
   }
   sx=cpl_image_get_size_x(img);
   sy=cpl_image_get_size_y(img);
   sx_sy=sx*sy;


   /* create the array of pointers to image data */
   pdata = cpl_malloc (nimg * sizeof (float *));
   assure (pdata != NULL, cpl_error_get_code (),
           "Cant allocate memory for data pointers");

   /* create the array of pointers to image binary */
   pbinary = cpl_malloc (nimg * sizeof (cpl_binary *));
   assure (pbinary != NULL, cpl_error_get_code (),
           "Cant allocate memory for binary pointers");

   /* Populate images pointer array */
   for (k = 0; k < nimg; k++) {
      check( pdata[k] = cpl_image_get_data_float(cpl_imagelist_get (iml, k)));
      check( pbinary[k] = cpl_mask_get_data(cpl_image_get_bpm(
                                               cpl_imagelist_get(iml, k))));
   }

   result=cpl_image_new(sx,sy,CPL_TYPE_FLOAT);
   pima=cpl_image_get_data_float(result);


   values=cpl_array_new(nimg,CPL_TYPE_FLOAT);

  /* Loop over all pixels */
  for (i = 0; i < sx_sy; i++){

     /* fill array only with good pixel values */
     for (count=0, k = 0; k < nimg; k++) {
        if ( ( (pbinary[k])[i] == CPL_BINARY_0) ) {
           cpl_array_set_float(values,k,(pdata[k])[i]);
           count++;
        } else {
           cpl_array_set_invalid(values,k);
        }

     } 
     /* finally compute mean and store result in output */
     mean=cpl_array_get_mean(values);

     pima[i]=mean;
  }

  cpl_array_delete(values);


  cleanup:

  cpl_array_delete(values);
  cpl_free(pdata);
  cpl_free(pbinary);


  return result;

}


cpl_error_code
xsh_imagelist_cut_dichroic_uvb(cpl_imagelist* org_data_iml,
                               cpl_imagelist* org_errs_iml,
                               cpl_imagelist* org_qual_iml,
                               cpl_propertylist* phead)
{

    cpl_vector* valid;
    double* data=NULL;

    int k=0;
    int naxis3=0;
    int zcut=0;

    double crval3=0;
    double cdelt3=0;
    double wave_cut=XSH_UVB_DICHROIC_WAVE_CUT; /* 556 nm dichroic cut */
    double wave_min=0;
    double wave_max=0;

    /* compute axis at which we need to cut */
    check(naxis3=cpl_imagelist_get_size(org_data_iml));
    crval3=xsh_pfits_get_crval3(phead);
    cdelt3=xsh_pfits_get_cdelt3(phead);

    wave_min = crval3;
    wave_max = wave_min + cdelt3*naxis3;
    cpl_ensure_code(wave_max > wave_cut, CPL_ERROR_ILLEGAL_INPUT);
    zcut = (int) ( (wave_cut-wave_min) / cdelt3 + 0.5 );
    cpl_ensure_code(zcut <= naxis3, CPL_ERROR_ILLEGAL_INPUT);

    if (zcut == naxis3) {
        return CPL_ERROR_NONE;
    }

    /* prepare vector to specify which image to erase */
    valid=cpl_vector_new(naxis3);
    cpl_vector_add_scalar(valid,1.);
    data=cpl_vector_get_data(valid);
    for(k=zcut+1;k<naxis3;k++) {
      data[k]=-1;
    }

    /* cut cubes */
    cpl_imagelist_erase(org_data_iml,valid);
    cpl_imagelist_erase(org_errs_iml,valid);
    cpl_imagelist_erase(org_qual_iml,valid);

    cleanup:
    xsh_free_vector(&valid);

    return cpl_error_get_code();
}


/**@}*/
