/* $Id: moses.c,v 1.116 2013/10/15 09:27:38 cgarcia Exp $
 *
 * This file is part of the MOSES library
 * Copyright (C) 2002-2010 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/15 09:27:38 $
 * $Revision: 1.116 $
 * $Name:  $
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <fors_overscan.h>
#include <hdrl_overscan.h>
#include <hdrl_parameter.h>
#include <hdrl_utils.h>

hdrl_parameter ** fors_overscan_get_regions(const cpl_propertylist *header,
                                            int &nregions);
hdrl_parameter ** fors_overscan_get_region_newdet(const cpl_propertylist *header);
hdrl_parameter ** fors_overscan_get_region_olddet(const cpl_propertylist *header);


/**
 * @brief
 *   Subtract the overscan from a CCD exposure
 *
 * @param image       Image containing the data to correct
 * @param header      Header of the image
 *
 * @return A newly allocated overscan subtracted image
 *
 */
cpl_image * fors_remove_overscan(cpl_image * image, cpl_propertylist * header)
{
/*    const char *func = "mos_remove_bias";

    cpl_image *unbiased;
    cpl_image *overscan;
    double     mean_bias_level;
    double     mean_overscans_level;
    int        count;
    int        nrows;
    int        xlow, ylow, xhig, yhig;
*/
    int        i;

    hdrl_parameter ** overscan_regions;
    int               nregions;
    
    if (image == NULL) 
    {
        cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
        return NULL;
    }

    overscan_regions = fors_overscan_get_regions(header, nregions);

    //count = 0;
    /* We cannot do it with HDRL, since it only accepts one region */
    //for (i = 0; i < nregions; i++) 
    //{
        //xlow = cpl_table_get_int(overscans, "xlow", i, NULL);
        //ylow = cpl_table_get_int(overscans, "ylow", i, NULL);
        //xhig = cpl_table_get_int(overscans, "xhig", i, NULL);
        //yhig = cpl_table_get_int(overscans, "yhig", i, NULL);

        //if (i == 0) 
        //{
            //unbiased = cpl_image_extract(image, xlow+1, ylow+1, xhig, yhig);
            //if (unbiased == NULL) {
                //cpl_msg_error(func, "Incompatible overscan table");
                //cpl_error_set(func, CPL_ERROR_INCOMPATIBLE_INPUT);
                //return NULL;
            //}
        //}
        //else {
            //overscan = cpl_image_extract(image, xlow+1, ylow+1, xhig, yhig);
            //if (overscan == NULL) {
                //cpl_msg_error(func, "Incompatible overscan table");
                //cpl_error_set(func, CPL_ERROR_INCOMPATIBLE_INPUT);
                //cpl_image_delete(unbiased);
       //         return NULL;
       //     }

            //mean_overscans_level += cpl_image_get_median(overscan);
            //count++;

            /***
             * Here the mean level was used: not very robust...

            mean_overscans_level += cpl_image_get_flux(overscan);
            count += cpl_image_get_size_x(overscan)
             * cpl_image_get_size_y(overscan);
             ***/
            //cpl_image_delete(overscan);
        //}
    //}

    /*
     * Overscan correction
     */

    //mean_overscans_level /= count;

    //cpl_image_subtract_scalar(unbiased, mean_overscans_level - mean_bias_level);

    //cpl_msg_info(cpl_func, 
    //             "Difference between mean overscans level "
    //             "and mean bias level: %.2f",
    //             mean_overscans_level - mean_bias_level);

    //return unbiased;
    return NULL;

}

hdrl_parameter ** fors_overscan_get_regions(const cpl_propertylist *header,
                                            int &nregions)
{
    int    nports;

    if (header == NULL) 
    {
        cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
        return NULL;
    }

    if (cpl_propertylist_has(header, "ESO DET OUTPUTS"))
        nports = cpl_propertylist_get_int(header, "ESO DET OUTPUTS");

    if (nports == 4                                        && 
        cpl_propertylist_has(header, "ESO DET OUT1 PRSCX") &&
        cpl_propertylist_has(header, "ESO DET WIN1 BINX")) 
    {
        //return fors_overscan_get_region_newdet(header);
    }
    else 
    {
        //return fors_overscan_get_region_olddet(header);
    }

    return NULL;
}

hdrl_parameter ** fors_overscan_get_region_newdet(const cpl_propertylist *header)
{

    int        nx = 0;
    int        ny = 0;
    int        px = 0;
    int        py = 0;
    int        ox = 0;
    int        oy = 0;
    int        rebin;
    hdrl_parameter ** overscan_regions;


    rebin = cpl_propertylist_get_int(header, "ESO DET WIN1 BINX");

    overscan_regions = (hdrl_parameter **)cpl_malloc(3 * sizeof(hdrl_parameter *));

    px = 16 / rebin;
    ox = 16 / rebin;
    nx = 2080 / rebin;
    ny = 2048 / rebin;

    overscan_regions[0] = hdrl_rect_region_parameter_create(px, py,
                                                            nx - ox, ny - oy);
    overscan_regions[1] = hdrl_rect_region_parameter_create(0, 0,
                                                            px, ny);
    overscan_regions[2] = hdrl_rect_region_parameter_create(nx - ox, 0,
                                                            nx, ny);

    return overscan_regions;
}

hdrl_parameter ** fors_overscan_get_region_oldet(const cpl_propertylist *header)
{

    int        nx = 0;
    int        ny = 0;
    int        px = 0;
    int        py = 0;
    int        ox = 0;
    int        oy = 0;
    size_t     nrows;
    size_t     irow;
    hdrl_parameter ** overscan_regions;

    if (cpl_propertylist_has(header, "NAXIS1"))
        nx = cpl_propertylist_get_int(header, "NAXIS1");
    if (cpl_propertylist_has(header, "NAXIS2"))
        ny = cpl_propertylist_get_int(header, "NAXIS2");
    if (cpl_propertylist_has(header, "ESO DET OUT1 PRSCX"))
        px = cpl_propertylist_get_int(header, "ESO DET OUT1 PRSCX");
    if (cpl_propertylist_has(header, "ESO DET OUT1 PRSCY"))
        py = cpl_propertylist_get_int(header, "ESO DET OUT1 PRSCY");
    if (cpl_propertylist_has(header, "ESO DET OUT1 OVSCX"))
        ox = cpl_propertylist_get_int(header, "ESO DET OUT1 OVSCX");
    if (cpl_propertylist_has(header, "ESO DET OUT1 OVSCY"))
        oy = cpl_propertylist_get_int(header, "ESO DET OUT1 OVSCY");

    if (cpl_error_get_code() != CPL_ERROR_NONE) 
    {
        cpl_msg_error(cpl_func, "Missing overscan keywords in header");
        cpl_error_set_where(cpl_func);
        return NULL;
    }

    if (px < 0 || py < 0 || ox < 0 || oy < 0) 
    {
        cpl_msg_error(cpl_func, "Missing overscan keywords in header");
        cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
        return NULL;
    }

    nrows = 0;
    if (px > 0)
        nrows++;
    if (ox > 0)
        nrows++;
    if (py > 0)
        nrows++;
    if (oy > 0)
        nrows++;

    if (nrows > 2) 
    {
        cpl_msg_error(cpl_func, "Unexpected overscan regions "
                      "(both in X and Y direction)");
        cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
        return NULL;
    }


    /*
     * A row is added for the description of the valid region of the
     * exposure the input header belongs to.
     */

    nrows++;

    overscan_regions = (hdrl_parameter **)
                       cpl_malloc(nrows * sizeof(hdrl_parameter *));

    irow = 0;
    overscan_regions[irow] = hdrl_rect_region_parameter_create(px, py,
                                                               nx - ox, ny - oy);
    irow++;

    if (px > 0) 
    {
        overscan_regions[irow] = hdrl_rect_region_parameter_create(0, 0,
                                                                   px, ny);
        irow++;
    }

    if (ox > 0) 
    {
        overscan_regions[irow] = hdrl_rect_region_parameter_create(nx - ox, 0,
                                                                   nx, ny);
        irow++;
    }

    if (py > 0) 
    {
        overscan_regions[irow] = hdrl_rect_region_parameter_create(0, 0,
                                                                   nx, py);
        irow++;
    }

    if (oy > 0) 
    {
        overscan_regions[irow] = hdrl_rect_region_parameter_create(0, ny - oy,
                                                                   nx, ny);
        irow++;
    }

    return overscan_regions;
}
