/*                                                                              *
 *   This file is part of the ESO VISIR package                                 *
 *   Copyright (C) 2004,2005 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       *
 *                                                                              */
 
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

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

#include <cpl.h>

#include <visir_utils.h>

/*----------------------------------------------------------------------------*/
/**
 * @defgroup visir_utils_test Testing of the VISIR utilities
 */
/*----------------------------------------------------------------------------*/

#define CONCAT(a,b) a ## _ ## b
#define CONCAT2X(a,b) CONCAT(a,b)

/*----------------------------------------------------------------------------*/
/**
   @brief   Unit tests of utils module
**/
/*----------------------------------------------------------------------------*/

int main(void)
{

    cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_WARNING);
    FILE          * stream;

    stream = cpl_msg_get_level() > CPL_MSG_INFO
        ? fopen("/dev/null", "a") : stdout;

    {
        visir_imglist * l = visir_imglist_new(10, NULL);
        cpl_propertylist * mplist = cpl_propertylist_new();
        cpl_test(l != NULL);
        cpl_test(visir_imglist_get_mplist(l) == NULL);
        cpl_test(visir_imglist_get_data(l ,9) == NULL);
        cpl_test_error(CPL_ERROR_ACCESS_OUT_OF_RANGE);
        cpl_test_leq(10, l->_capacity);
        cpl_test_eq(0, visir_imglist_get_size(l));
        visir_imglist_delete(l, NULL);
        cpl_test_error(CPL_ERROR_NONE);

        l = visir_imglist_new(10, mplist);
        cpl_test(visir_imglist_get_mplist(l) == mplist);
        visir_imglist_set_mplist(l, NULL);
        visir_imglist_delete(l, NULL);
        cpl_test_error(CPL_ERROR_NONE);

        l = visir_imglist_new(0, mplist);
        cpl_test(visir_imglist_get_mplist(l) == mplist);
        cpl_test_lt(0, l->_capacity);
        cpl_test_noneq_ptr(l->auxdata, (void*)NULL);
        cpl_test_noneq_ptr(l->imgs, (void*)NULL);
        visir_imglist_delete(l, cpl_free);
        cpl_test_error(CPL_ERROR_NONE);
        cpl_propertylist_delete(mplist);

        visir_imglist_delete(NULL, NULL);
        visir_imglist_delete(NULL, cpl_free);
        visir_imglist_unwrap(NULL, NULL);
        cpl_test_error(CPL_ERROR_NONE);
    }

    {
        visir_imglist * l = visir_imglist_new(1, NULL);
        const int N = 10;
        cpl_image * imgs[N];
        cpl_propertylist * plists[N];
        for (int i = 0; i < N; i++) {
            imgs[i] = cpl_image_new(3, 3, CPL_TYPE_INT);
            plists[i] = cpl_propertylist_new();
        }
        cpl_propertylist_delete(plists[3]);
        plists[3] = NULL;

        for (cpl_size i = 0; i < N; i++) {
            visir_imglist_append(l, imgs[i], plists[i]);
            cpl_test_image_abs(visir_imglist_get_img(l, i), imgs[i], 0);
            cpl_test_eq_ptr(visir_imglist_get_data(l, i), plists[i]);
        }
        cpl_test_eq(N, visir_imglist_get_size(l));
        cpl_test_leq(visir_imglist_get_size(l), l->_capacity);

        for (cpl_size i = 0; i < N; i++) {
            cpl_propertylist * p;
            cpl_image * img;
            visir_imglist_get(l, i, &img, (void**)&p);
            cpl_test_eq_ptr(img, imgs[i]);
            cpl_test_eq_ptr(p, plists[i]);
            visir_imglist_get(l, i, &img, NULL);
            cpl_test_eq_ptr(img, imgs[i]);
            visir_imglist_get(l, i, NULL, (void**)&p);
            cpl_test_eq_ptr(p, plists[i]);
            visir_imglist_get(l, i, NULL, NULL);
        }

        cpl_test(visir_imglist_get_img(l, -1) == NULL);
        cpl_test_error(CPL_ERROR_ACCESS_OUT_OF_RANGE);
        cpl_test(visir_imglist_get_img(l, N + 1) == NULL);
        cpl_test_error(CPL_ERROR_ACCESS_OUT_OF_RANGE);
        cpl_test(visir_imglist_get_data(l, -1) == NULL);
        cpl_test_error(CPL_ERROR_ACCESS_OUT_OF_RANGE);
        cpl_test(visir_imglist_get_data(l, N + 1) == NULL);
        cpl_test_error(CPL_ERROR_ACCESS_OUT_OF_RANGE);

        visir_imglist_delete(l, (visir_free)cpl_propertylist_delete);
    }

    {
        visir_imglist * l = visir_imglist_new(1, NULL);
        const int N = 10;
        cpl_image * imgs[N];
        cpl_propertylist * plists[N];
        for (int i = 0; i < N; i++) {
            imgs[i] = cpl_image_new(3, 3, CPL_TYPE_INT);
            plists[i] = cpl_propertylist_new();
        }
        cpl_propertylist_delete(plists[3]);
        plists[3] = NULL;

        for (cpl_size i = 0; i < N; i++) {
            visir_imglist_append(l, imgs[i], plists[i]);
            cpl_test_image_abs(visir_imglist_get_img(l, i), imgs[i], 0);
            cpl_test_eq_ptr(visir_imglist_get_data(l, i), plists[i]);
        }

        visir_imglist_unwrap(l, (visir_free)cpl_propertylist_delete);
        for (cpl_size i = 0; i < N; i++)
            cpl_image_delete(imgs[i]);
    }

    {
        visir_imglist * l = visir_imglist_new(1, NULL);
        const int N = 10;
        void * data = cpl_malloc(4);
        void * data2 = cpl_malloc(4);
        cpl_imagelist * imgs = cpl_imagelist_new();
        for (int i = 0; i < N; i++)
            cpl_imagelist_set(imgs, cpl_image_new(3, 3, CPL_TYPE_INT), i);

        visir_imglist_append_imglist(l, imgs, NULL);
        cpl_test_error(CPL_ERROR_NONE);

        visir_imglist_set_data(l, 3, data);
        visir_imglist_set_data(l, 4, data2);
        cpl_test_error(CPL_ERROR_NONE);

        cpl_test_eq(N, visir_imglist_get_size(l));
        cpl_test_leq(visir_imglist_get_size(l), l->_capacity);

        for (cpl_size i = 0; i < visir_imglist_get_size(l); i++) {
            cpl_test_image_abs(visir_imglist_get_img(l, i),
                               cpl_imagelist_get(imgs, i), 0);
        }

        cpl_test_eq_ptr(visir_imglist_get_data(l, 3), data);
        cpl_test_eq_ptr(visir_imglist_get_data(l, 4), data2);
        cpl_imagelist_delete(imgs);
        visir_imglist * nl = visir_imglist_new(1, visir_imglist_get_mplist(l));
        for (cpl_size i = 0; i < visir_imglist_get_size(l); i++) {
            visir_imglist_append(nl, visir_imglist_get_img(l, i),
                                 visir_imglist_get_data(l, i));
        }
        cpl_test_eq(visir_imglist_get_size(l), visir_imglist_get_size(nl));
        visir_imglist_unwrap(l, NULL);
        visir_imglist_delete(nl, cpl_free);
    }

    if (stream != stdout) cpl_test_zero( fclose(stream) );
    return cpl_test_end(0);
}
