/*
 * This file is part of the KMOS Library
 * Copyright (C) 2007-2008 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
 */

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

#include "kmclipm_constants.h"
#include "kmclipm_functions.h"

#include "kmo_priv_fits_stack.h"
#include "kmo_cpl_extensions.h"
#include "kmo_debug.h"
#include "kmo_dfs.h"

/**
    @defgroup kmo_priv_fits_stack_test   kmo_priv_fits_stack unit tests

    @{
*/

void kmo_test_verbose_off();
void kmo_test_verbose_on();

/**
    @brief   test for kmo_priv_fits_stack()
*/
void test_kmo_priv_fits_stack()
{
    cpl_parameterlist   *parlist    = NULL;
    cpl_frameset        *fs         = NULL,
                        *fs_copy    = NULL,
                        *fs_badpix  = NULL;
    cpl_parameter       *ptype      = NULL,
                        *pfn        = NULL,
                        *pmainkey   = NULL,
                        *pvalid     = NULL;
    cpl_frame           *f          = NULL;
    cpl_image           *img        = NULL;
    cpl_propertylist    *prl        = NULL;
    enum kmo_frame_type type        = illegal_fits;
    int                 id          = 0;
    char                content[64];
    const char          *extname    = NULL;

    /* --- invalid tests --- */
    kmo_test_verbose_off();

    /* NULL input */
    cpl_test_eq(-1, kmo_priv_fits_stack(NULL, NULL));
    cpl_test_error(CPL_ERROR_NULL_INPUT);

    parlist = cpl_parameterlist_new();
    fs = cpl_frameset_new();

    /* empty frameset */
    cpl_test_eq(-1, kmo_priv_fits_stack(parlist, fs));
    cpl_test_error(CPL_ERROR_ILLEGAL_INPUT);

    /* empty parameterlist, type missing */
    f = cpl_frame_new();
    cpl_frame_set_filename(f, "img1.fits");
    cpl_frame_set_tag(f, FS_DATA);
    cpl_frameset_insert(fs, f);
    img = cpl_image_new(5, 5, CPL_TYPE_FLOAT);
    kmo_image_fill(img, 0.5);
    cpl_image_save(img, "img1.fits", CPL_BPP_IEEE_FLOAT, NULL, CPL_IO_DEFAULT);

    cpl_test_eq(-1, kmo_priv_fits_stack(parlist, fs));
    cpl_test_error(CPL_ERROR_ILLEGAL_INPUT);

    /* 3 frames needed */
    pvalid = cpl_parameter_new_value("kmos.kmo_fits_stack.valid",
                                CPL_TYPE_STRING,
                                "gaga",
                                "kmos.kmo_fits_stack",
                                "");
    cpl_parameter_set_alias(pvalid, CPL_PARAMETER_MODE_CLI, "valid");
    cpl_parameterlist_append(parlist, pvalid);

    ptype = cpl_parameter_new_value("kmos.kmo_fits_stack.type",
                                CPL_TYPE_STRING,
                                "gaga",
                                "kmos.kmo_fits_stack",
                                "RAW");
    cpl_parameter_set_alias(ptype, CPL_PARAMETER_MODE_CLI, "type");
    cpl_parameterlist_append(parlist, ptype);
    cpl_test_eq(-1, kmo_priv_fits_stack(parlist, fs));
    cpl_test_error(CPL_ERROR_ILLEGAL_INPUT);

    /* filename missing */
    f = cpl_frame_new();
    cpl_frame_set_filename(f, "img2.fits");
    cpl_frame_set_tag(f, FS_DATA);
    cpl_frameset_insert(fs, f);
    kmo_image_fill(img, 0.6);
    cpl_image_save(img, "img2.fits", CPL_BPP_IEEE_FLOAT, NULL, CPL_IO_DEFAULT);

    f = cpl_frame_new();
    cpl_frame_set_filename(f, "img3.fits");
    cpl_frame_set_tag(f, FS_DATA);
    cpl_frameset_insert(fs, f);
    kmo_image_fill(img, 0.7);
    cpl_image_save(img, "img3.fits", CPL_BPP_IEEE_FLOAT, NULL, CPL_IO_DEFAULT);

    cpl_test_eq(-1, kmo_priv_fits_stack(parlist, fs));
    cpl_test_error(CPL_ERROR_NULL_INPUT);

    fs_copy = cpl_frameset_duplicate(fs);

    kmo_test_verbose_on();

    /* --- valid tests --- */
    /* raw, no mainkeys, no subkeys */
    pfn = cpl_parameter_new_value("kmos.kmo_fits_stack.filename",
                                CPL_TYPE_STRING,
                                "gaga",
                                "kmos.kmo_fits_stack",
                                "stacked_raw");
    cpl_parameter_set_alias(pfn, CPL_PARAMETER_MODE_CLI, "filename");
    cpl_parameterlist_append(parlist, pfn);

    cpl_test_eq(0, kmo_priv_fits_stack(parlist, fs));
    cpl_test_error(CPL_ERROR_NONE);
    cpl_frameset_delete(fs); fs = cpl_frameset_duplicate(fs_copy);

    prl = kmclipm_propertylist_load("stacked_raw.fits", 1);
    cpl_test_eq(1, cpl_propertylist_get_int(prl, "ESO DET CHIP INDEX"));
    cpl_propertylist_delete(prl);
    prl = kmclipm_propertylist_load("stacked_raw.fits", 2);
    cpl_test_eq(2, cpl_propertylist_get_int(prl, "ESO DET CHIP INDEX"));
    cpl_propertylist_delete(prl);

    /* f2d, no mainkeys, no subkeys */
    cpl_parameterlist_delete(parlist);
    parlist = cpl_parameterlist_new();
    pvalid = cpl_parameter_new_value("kmos.kmo_fits_stack.valid",
                                CPL_TYPE_STRING,
                                "gaga",
                                "kmos.kmo_fits_stack",
                                "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1");
    cpl_parameter_set_alias(pvalid, CPL_PARAMETER_MODE_CLI, "valid");
    cpl_parameterlist_append(parlist, pvalid);

    ptype = cpl_parameter_new_value("kmos.kmo_fits_stack.type",
                                CPL_TYPE_STRING,
                                "gaga",
                                "kmos.kmo_fits_stack",
                                "F2D");
    cpl_parameter_set_alias(ptype, CPL_PARAMETER_MODE_CLI, "type");
    cpl_parameterlist_append(parlist, ptype);
    pfn = cpl_parameter_new_value("kmos.kmo_fits_stack.filename",
                                CPL_TYPE_STRING,
                                "gaga",
                                "kmos.kmo_fits_stack",
                                "stacked_f2d");
    cpl_parameter_set_alias(pfn, CPL_PARAMETER_MODE_CLI, "filename");
    cpl_parameterlist_append(parlist, pfn);
    cpl_test_eq(0, kmo_priv_fits_stack(parlist, fs));
    cpl_test_error(CPL_ERROR_NONE);

    prl = kmclipm_propertylist_load("stacked_f2d.fits", 1);
    extname = cpl_propertylist_get_string(prl, EXTNAME);
    kmo_extname_extractor(extname, &type, &id, content);
    cpl_propertylist_delete(prl);
    cpl_test_eq(type, detector_frame);
    cpl_test_eq(id, 1);
    cpl_test_eq(0, strcmp(content, EXT_DATA));

    prl = kmclipm_propertylist_load("stacked_f2d.fits", 2);
    extname = cpl_propertylist_get_string(prl, EXTNAME);
    kmo_extname_extractor(extname, &type, &id, content);
    cpl_propertylist_delete(prl);
    cpl_test_eq(type, detector_frame);
    cpl_test_eq(id, 2);
    cpl_test_eq(0, strcmp(content, EXT_DATA));

    prl = kmclipm_propertylist_load("stacked_f2d.fits", 3);
    extname = cpl_propertylist_get_string(prl, EXTNAME);
    kmo_extname_extractor(extname, &type, &id, content);
    cpl_propertylist_delete(prl);
    cpl_test_eq(type, detector_frame);
    cpl_test_eq(id, 3);
    cpl_test_eq(0, strcmp(content, EXT_DATA));

    /* b2d, badpix, mainkeys, no subkeys */
    fs_badpix = cpl_frameset_new();
    f = cpl_frame_new();
    cpl_frame_set_filename(f, "img1.fits");
    cpl_frame_set_tag(f, FS_BADPIX);
    cpl_frameset_insert(fs_badpix, f);
    f = cpl_frame_new();
    cpl_frame_set_filename(f, "img2.fits");
    cpl_frame_set_tag(f, FS_BADPIX);
    cpl_frameset_insert(fs_badpix, f);
    f = cpl_frame_new();
    cpl_frame_set_filename(f, "img3.fits");
    cpl_frame_set_tag(f, FS_BADPIX);
    cpl_frameset_insert(fs_badpix, f);

    cpl_parameterlist_delete(parlist);
    parlist = cpl_parameterlist_new();
    pvalid = cpl_parameter_new_value("kmos.kmo_fits_stack.valid",
                                CPL_TYPE_STRING,
                                "gaga",
                                "kmos.kmo_fits_stack",
                                "1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1");
    cpl_parameter_set_alias(pvalid, CPL_PARAMETER_MODE_CLI, "valid");
    cpl_parameterlist_append(parlist, pvalid);

    ptype = cpl_parameter_new_value("kmos.kmo_fits_stack.type",
                                CPL_TYPE_STRING,
                                "gaga",
                                "kmos.kmo_fits_stack",
                                "B2D");
    cpl_parameter_set_alias(ptype, CPL_PARAMETER_MODE_CLI, "type");
    cpl_parameterlist_append(parlist, ptype);
    pfn = cpl_parameter_new_value("kmos.kmo_fits_stack.filename",
                                CPL_TYPE_STRING,
                                "gaga",
                                "kmos.kmo_fits_stack",
                                "stacked_b2d_badpix");
    cpl_parameter_set_alias(pfn, CPL_PARAMETER_MODE_CLI, "filename");
    cpl_parameterlist_append(parlist, pfn);
    pmainkey = cpl_parameter_new_value("kmos.kmo_fits_stack.mainkey",
                                CPL_TYPE_STRING,
                                "gaga",
                                "kmos.kmo_fits_stack",
                                "DADA;int;3;GAGA;double;1.1");
    cpl_parameter_set_alias(pmainkey, CPL_PARAMETER_MODE_CLI, "mainkey");
    cpl_parameterlist_append(parlist, pmainkey);
    cpl_test_eq(0, kmo_priv_fits_stack(parlist, fs_badpix));
    cpl_test_error(CPL_ERROR_NONE);

    prl = kmclipm_propertylist_load("stacked_b2d_badpix.fits", 0);
    cpl_test_eq(3, cpl_propertylist_get_int(prl, "DADA"));
    cpl_test_eq(1.1, cpl_propertylist_get_double(prl, "GAGA"));
    cpl_propertylist_delete(prl);

    prl = kmclipm_propertylist_load("stacked_b2d_badpix.fits", 1);
    extname = cpl_propertylist_get_string(prl, EXTNAME);
    kmo_extname_extractor(extname, &type, &id, content);
    cpl_propertylist_delete(prl);
    cpl_test_eq(type, detector_frame);
    cpl_test_eq(id, 1);
    cpl_test_eq(0, strcmp(content, EXT_BADPIX));

    prl = kmclipm_propertylist_load("stacked_b2d_badpix.fits", 2);
    extname = cpl_propertylist_get_string(prl, EXTNAME);
    kmo_extname_extractor(extname, &type, &id, content);
    cpl_propertylist_delete(prl);
    cpl_test_eq(type, detector_frame);
    cpl_test_eq(id, 2);
    cpl_test_eq(0, strcmp(content, EXT_BADPIX));

    prl = kmclipm_propertylist_load("stacked_b2d_badpix.fits", 3);
    extname = cpl_propertylist_get_string(prl, EXTNAME);
    kmo_extname_extractor(extname, &type, &id, content);
    cpl_propertylist_delete(prl);
    cpl_test_eq(type, detector_frame);
    cpl_test_eq(id, 3);
    cpl_test_eq(0, strcmp(content, EXT_BADPIX));

    /* f2i, no mainkeys but subkeys */
    cpl_frameset_delete(fs);
    fs = cpl_frameset_new();
    f = cpl_frame_new();
    cpl_frame_set_filename(f, "img1.fits");
    cpl_frame_set_tag(f, FS_DATA);
    cpl_frameset_insert(fs, f);
    f = cpl_frame_new();
    cpl_frame_set_filename(f, "img1.fits");
    cpl_frame_set_tag(f, FS_NOISE);
    cpl_frameset_insert(fs, f);
    f = cpl_frame_new();
    cpl_frame_set_filename(f, "img2.fits");
    cpl_frame_set_tag(f, FS_DATA);
    cpl_frameset_insert(fs, f);
    f = cpl_frame_new();
    cpl_frame_set_filename(f, "img2.fits");
    cpl_frame_set_tag(f, FS_NOISE);
    cpl_frameset_insert(fs, f);
    f = cpl_frame_new();
    cpl_frame_set_filename(f, "img3.fits");
    cpl_frame_set_tag(f, FS_DATA);
    cpl_frameset_insert(fs, f);
    f = cpl_frame_new();
    cpl_frame_set_filename(f, "img3.fits");
    cpl_frame_set_tag(f, FS_NOISE);
    cpl_frameset_insert(fs, f);

    cpl_parameterlist_delete(parlist);
    parlist = cpl_parameterlist_new();
    pvalid = cpl_parameter_new_value("kmos.kmo_fits_stack.valid",
                                CPL_TYPE_STRING,
                                "gaga",
                                "kmos.kmo_fits_stack",
                                "");
    cpl_parameter_set_alias(pvalid, CPL_PARAMETER_MODE_CLI, "valid");
    cpl_parameterlist_append(parlist, pvalid);

    ptype = cpl_parameter_new_value("kmos.kmo_fits_stack.type",
                                CPL_TYPE_STRING,
                                "gaga",
                                "kmos.kmo_fits_stack",
                                "F2I");
    cpl_parameter_set_alias(ptype, CPL_PARAMETER_MODE_CLI, "type");
    cpl_parameterlist_append(parlist, ptype);
    pfn = cpl_parameter_new_value("kmos.kmo_fits_stack.filename",
                                CPL_TYPE_STRING,
                                "gaga",
                                "kmos.kmo_fits_stack",
                                "stacked_f2i");
    cpl_parameter_set_alias(pfn, CPL_PARAMETER_MODE_CLI, "filename");
    cpl_parameterlist_append(parlist, pfn);
    pmainkey = cpl_parameter_new_value("kmos.kmo_fits_stack.subkey",
                                CPL_TYPE_STRING,
                                "gaga",
                                "kmos.kmo_fits_stack",
                                "DADA;int;3;GAGA;double;1.1");
    cpl_parameter_set_alias(pmainkey, CPL_PARAMETER_MODE_CLI, "subkey");
    cpl_parameterlist_append(parlist, pmainkey);
    cpl_test_eq(0, kmo_priv_fits_stack(parlist, fs));
    cpl_test_error(CPL_ERROR_NONE);

    prl = kmclipm_propertylist_load("stacked_f2i.fits", 1);
    extname = cpl_propertylist_get_string(prl, EXTNAME);
    kmo_extname_extractor(extname, &type, &id, content);
    cpl_test_eq(type, ifu_frame);
    cpl_test_eq(id, 1);
    cpl_test_eq(0, strcmp(content, EXT_DATA));
    cpl_test_eq(3, cpl_propertylist_get_int(prl, "DADA"));
    cpl_test_eq(1.1, cpl_propertylist_get_double(prl, "GAGA"));
    cpl_propertylist_delete(prl);

    prl = kmclipm_propertylist_load("stacked_f2i.fits", 2);
    extname = cpl_propertylist_get_string(prl, EXTNAME);
    kmo_extname_extractor(extname, &type, &id, content);
    cpl_test_eq(type, ifu_frame);
    cpl_test_eq(id, 1);
    cpl_test_eq(0, strcmp(content, EXT_NOISE));
    cpl_test_eq(3, cpl_propertylist_get_int(prl, "DADA"));
    cpl_test_eq(1.1, cpl_propertylist_get_double(prl, "GAGA"));
    cpl_propertylist_delete(prl);

    prl = kmclipm_propertylist_load("stacked_f2i.fits", 3);
    extname = cpl_propertylist_get_string(prl, EXTNAME);
    kmo_extname_extractor(extname, &type, &id, content);
    cpl_test_eq(type, ifu_frame);
    cpl_test_eq(id, 2);
    cpl_test_eq(0, strcmp(content, EXT_DATA));
    cpl_test_eq(3, cpl_propertylist_get_int(prl, "DADA"));
    cpl_test_eq(1.1, cpl_propertylist_get_double(prl, "GAGA"));
    cpl_propertylist_delete(prl);

    prl = kmclipm_propertylist_load("stacked_f2i.fits", 4);
    extname = cpl_propertylist_get_string(prl, EXTNAME);
    kmo_extname_extractor(extname, &type, &id, content);
    cpl_test_eq(type, ifu_frame);
    cpl_test_eq(id, 2);
    cpl_test_eq(0, strcmp(content, EXT_NOISE));
    cpl_test_eq(3, cpl_propertylist_get_int(prl, "DADA"));
    cpl_test_eq(1.1, cpl_propertylist_get_double(prl, "GAGA"));
    cpl_propertylist_delete(prl);

    prl = kmclipm_propertylist_load("stacked_f2i.fits", 5);
    extname = cpl_propertylist_get_string(prl, EXTNAME);
    kmo_extname_extractor(extname, &type, &id, content);
    cpl_test_eq(type, ifu_frame);
    cpl_test_eq(id, 3);
    cpl_test_eq(0, strcmp(content, EXT_DATA));
    cpl_test_eq(3, cpl_propertylist_get_int(prl, "DADA"));
    cpl_test_eq(1.1, cpl_propertylist_get_double(prl, "GAGA"));
    cpl_propertylist_delete(prl);

    prl = kmclipm_propertylist_load("stacked_f2i.fits", 6);
    extname = cpl_propertylist_get_string(prl, EXTNAME);
    kmo_extname_extractor(extname, &type, &id, content);
    cpl_test_eq(type, ifu_frame);
    cpl_test_eq(id, 3);
    cpl_test_eq(0, strcmp(content, EXT_NOISE));
    cpl_test_eq(3, cpl_propertylist_get_int(prl, "DADA"));
    cpl_test_eq(1.1, cpl_propertylist_get_double(prl, "GAGA"));
    cpl_propertylist_delete(prl);

    cpl_parameterlist_delete(parlist);
    cpl_frameset_delete(fs);
    cpl_frameset_delete(fs_copy);
    cpl_frameset_delete(fs_badpix);
    cpl_image_delete(img);

    cpl_test_error(CPL_ERROR_NONE);
}

/**
    @brief   test for kmo_priv_check_dimensions()
*/
void test_kmo_priv_check_dimensions()
{
    /* --- invalid tests --- */
    kmo_test_verbose_off();
    kmo_priv_check_dimensions(NULL, 0, 0, 0, 0);
    cpl_test_error(CPL_ERROR_NULL_INPUT);

    cpl_propertylist *pl = cpl_propertylist_new();
    kmo_priv_check_dimensions(pl, 0, 0, 0, 0);
    cpl_test_error(CPL_ERROR_ILLEGAL_INPUT);
    kmo_test_verbose_on();

    /* --- valid tests --- */
    kmclipm_update_property_int(pl, "NAXIS", 3, "");
    kmclipm_update_property_int(pl, "NAXIS1", 2, "");
    kmclipm_update_property_int(pl, "NAXIS2", 3, "");
    kmclipm_update_property_int(pl, "NAXIS3", 4, "");
    kmo_priv_check_dimensions(pl, 3, 2, 3, 4);
    cpl_test_error(CPL_ERROR_NONE);
    cpl_propertylist_delete(pl);
}

/**
    @brief   Test of helper functions for kmo_fits_stack
*/
int main()
{
    cpl_test_init("<usd-help@eso.org>", CPL_MSG_WARNING);

    /* test_kmo_priv_fits_stack(); */
    test_kmo_priv_check_dimensions();

    return cpl_test_end(0);
}

/** @} */
