/* $Id: hdrl_utils.h,v 1.4 2013-10-16 18:00:33 cgarcia Exp $
 *
 * This file is part of the HDRL
 * Copyright (C) 2012,2013 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

/*
 * $Author: cgarcia $
 * $Date: 2013-10-16 18:00:33 $
 * $Revision: 1.4 $
 * $Name: not supported by cvs2svn $
 */

#ifndef HDRL_UTILS_H
#define HDRL_UTILS_H

/*-----------------------------------------------------------------------------
                                Includes
 -----------------------------------------------------------------------------*/

#include <cpl.h>
#include "hdrl_parameter.h"
#include <stdlib.h>

/*-----------------------------------------------------------------------------
                                Define
 -----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*/
/**
  @enum hdrl_direction
  @brief Define an image direction e.g along X or Y
 */
/*----------------------------------------------------------------------------*/
typedef enum {

    /** X axis, equivalent to NAXIS1 in FITS convention */ 
    HDRL_X_AXIS,
    /** Y axis, equivalent to NAXIS2 in FITS convention */ 
    HDRL_Y_AXIS,
    /** Reserved value for undefined direction */ 
    HDRL_UNDEFINED_AXIS
} hdrl_direction;

typedef enum {
    HDRL_SCALE_ADDITIVE,
    HDRL_SCALE_MULTIPLICATIVE
} hdrl_scale_type;

/*-----------------------------------------------------------------------------
                            Functions prototypes
 -----------------------------------------------------------------------------*/
CPL_BEGIN_DECLS

const char * hdrl_get_license(void);

/*----------------------------------------------------------------------------
                           Rect region Parameters
  ----------------------------------------------------------------------------*/
hdrl_parameter * hdrl_rect_region_parameter_create(cpl_size, cpl_size,
        cpl_size, cpl_size) ;
cpl_error_code hdrl_rect_region_parameter_update(hdrl_parameter *, cpl_size, 
        cpl_size, cpl_size, cpl_size) ;
cpl_boolean hdrl_rect_region_parameter_check(const hdrl_parameter *) ;
cpl_size hdrl_rect_region_get_llx(const hdrl_parameter *) ;
cpl_size hdrl_rect_region_get_lly(const hdrl_parameter *) ;
cpl_size hdrl_rect_region_get_urx(const hdrl_parameter *) ;
cpl_size hdrl_rect_region_get_ury(const hdrl_parameter *) ;
cpl_error_code hdrl_rect_region_parameter_verify(const hdrl_parameter *,
        const cpl_size, const cpl_size) ;
cpl_error_code hdrl_rect_region_wrap(hdrl_parameter *, const cpl_size,
        const cpl_size) ;
cpl_parameterlist * hdrl_rect_region_parameter_create_parlist(const char *, 
        const char *, const char *, const char *, const hdrl_parameter *) ;
hdrl_parameter * hdrl_rect_region_parameter_parse_parlist(
        const cpl_parameterlist *, const char *, const char *) ;
/*----------------------------------------------------------------------------*/

int hdrl_get_tempfile(const char * dir, cpl_boolean unlink);

cpl_error_code hdrl_calc_mean_image(const cpl_image * ima,
                                    const cpl_image * err, double * mean,
                                    double * meanerr);

cpl_error_code hdrl_calc_weighted_mean_image( const cpl_image * ima,
                                      const cpl_image * err, double * wmean,
                                      double * wmeanerr);

cpl_error_code hdrl_calc_median_image(const cpl_image * ima,
                                      const cpl_image * err, double * median,
                                      double * medianerr);

cpl_error_code
hdrl_normalize_imagelist_by_vector(const cpl_vector * vector,
                                   const cpl_vector * evector,
                                   hdrl_scale_type scale_type,
                                   cpl_imagelist * data,
                                   cpl_imagelist * errors);

cpl_error_code
hdrl_normalize_imagelist_by_imagelist(const cpl_imagelist * scale,
                                      const cpl_imagelist * scale_e,
                                      const hdrl_scale_type scale_type,
                                      cpl_imagelist * data,
                                      cpl_imagelist * errors);

cpl_error_code
hdrl_detector_shotnoise_model(const cpl_image* ima_data, const double conad,
                                  const double ron, cpl_image ** ima_errs);
cpl_error_code
hdrl_detector_shotnoise_model_bias(const cpl_image* ima_data, const double ron,
                                   cpl_image ** ima_errs);
CPL_END_DECLS

/*-----------------------------------------------------------------------------
             Private declarations - must not be used outside of hdrl
 -----------------------------------------------------------------------------*/

#ifdef HDRL_USE_PRIVATE

/* setup a value parameter and append it into parlist */
#define hdrl_setup_vparameter(parlist, \
                              full_prefix, \
                              full_sep, \
                              name_prefix, \
                              alias_prefix, \
                              alias_sep, \
                              pname, \
                              context, \
                              descr, \
                              type, \
                              pdefault) \
do { \
        char * name = cpl_sprintf("%s%s%s%s", full_prefix, full_sep, \
                                  name_prefix, pname); \
        cpl_parameter * p = cpl_parameter_new_value(name, type, \
                descr, context, pdefault) ; \
        cpl_free(name); \
        name = cpl_sprintf("%s%s%s%s", alias_prefix, alias_sep, \
                           name_prefix, pname); \
        cpl_parameter_set_alias(p, CPL_PARAMETER_MODE_CLI, name); \
        cpl_free(name); \
        cpl_parameterlist_append(parlist, p); \
    } while (0)

cpl_vector * hdrl_image_to_vector(const cpl_image * source, const
        cpl_mask * bpm);
cpl_vector * hdrl_imagelist_to_vector(const cpl_imagelist * source, 
        const cpl_size x, const cpl_size y);

static inline int hdrl_int_is_power_of_two(unsigned long long x)
{
    return (x & (x - 1)) == 0;
}

static inline size_t hdrl_get_image_npix(const cpl_image * img)
{
    return cpl_image_get_size_x(img) * cpl_image_get_size_y(img);
}

static inline size_t hdrl_get_image_good_npix(const cpl_image * img)
{
    return (cpl_image_get_size_x(img) * cpl_image_get_size_y(img)) -
        cpl_image_count_rejected(img);
}

static inline cpl_mask * hdrl_copy_image_mask(const cpl_image * img)
{
    /* always returns a mask even it image has none */
    const cpl_mask * bpm = cpl_image_get_bpm_const(img);

    if (bpm) {
        return cpl_mask_duplicate(bpm);
    }
    else {
        return cpl_mask_new(cpl_image_get_size_x(img),
                            cpl_image_get_size_y(img));
    }
}

#endif

#endif
