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

float   test_global_seed_data            = 1.1;

/**
    @brief Switches off error-messages.
*/
void kmo_test_verbose_off()
{
    if (getenv("KMO_TEST_VERBOSE") == NULL) {
        cpl_msg_set_level(CPL_MSG_OFF);
    }
}

/**
    @brief Switches on error-messages.
*/
void kmo_test_verbose_on()
{
    if (getenv("KMO_TEST_VERBOSE") == NULL) {
        cpl_msg_set_level(CPL_MSG_WARNING);
    }
}

/**
    @brief
        Frame constructor

    @param   filename         frame filename
    @param   tag              frame tag
    @param   group            frame group

    @return  Newly allocated frame with the given contents.
 */
cpl_frame* kmo_test_frame_new(const char *filename,
                              const char *tag,
                              cpl_frame_group group)
{
    cpl_frame   *f      = NULL;

    KMO_TRY
    {
        f = cpl_frame_new();
        KMO_TRY_EXIT_IF_NOT(f != NULL);

        cpl_frame_set_filename(f, filename);

        cpl_frame_set_tag(f, tag);

        cpl_frame_set_group(f, group);
    }
    KMO_CATCH
    {
        f = NULL;
    }

    return f;
}

/**
    @brief Fills a vector with increasing values.

    @param   vec         The vector to fill with values.
    @param   seed        The starting value.
    @param   offset      The offset for the values.

 */
void kmo_test_fill_vector(cpl_vector *vec,
                          float seed,
                          float offset)
{
    int         i       = 0,
                size    = 0;
    double      *data   = NULL;

    KMO_TRY
    {
        size = cpl_vector_get_size(vec);
        KMO_TRY_EXIT_IF_NOT(size > 0);

        data = cpl_vector_get_data(vec);
        KMO_TRY_EXIT_IF_NOT(data != NULL);

        // horizontal stripes: bottom = 0, top = seed * (y-1)
        for (i = 0; i < size; i++) {
                data[i] = seed + i * offset;
        }
    }
    KMO_CATCH
    {
    }
}

/******************************************************************************/
/**
  @brief    Fills an image with increasing values.
  @param    img     The image to fill with values.
  @param    seed    The starting value.
  @param    offset  The offset for the values.
 */
/******************************************************************************/
void kmo_test_fill_image(
        cpl_image   *   img,
        float           seed,
        float           offset)
{
    cpl_size    npix    = 0;
    float   *   data    = NULL ;
    cpl_size    i ;

    npix = cpl_image_get_size_x(img) * cpl_image_get_size_y(img);
    data = cpl_image_get_data_float(img);
    if (data == NULL) return ;

    for (i=0 ; i<npix ; i++) data[i] = seed + offset*i ;
}

/**
    @brief Fills a cube with increasing values.

    @param   cube        The cube to fill with values.
    @param   seed        The starting value.
    @param   offset      The offset for the values.

 */
void kmo_test_fill_cube(cpl_imagelist *cube,
                        float seed,
                        float offset)
{
    int         i       = 0,
                size    = 0;

    KMO_TRY
    {
        size = cpl_imagelist_get_size(cube);
        KMO_TRY_EXIT_IF_NOT(size > 0);

        for (i = 0; i < size; i++) {
            kmo_test_fill_image(cpl_imagelist_get(cube, i),
                                seed, offset);
            seed += offset;
        }
    }
    KMO_CATCH
    {
    }
}

/**
    @brief Allocates images in an empty imagelist.

    @param   cube        The cube to allocate.
    @param   x           Size in x-dimension.
    @param   y           Size in y-dimension.
    @param   z           Size in z-dimension.

 */
void kmo_test_alloc_cube(cpl_imagelist *cube,
                         int x,
                         int y,
                         int z)
{
    int         i       = 0;
    cpl_image   *img    = NULL;

    KMO_TRY
    {
        KMO_TRY_EXIT_IF_NOT(cpl_imagelist_get_size(cube) == 0);

        for (i = 0; i < z; i++) {
            KMO_TRY_EXIT_IF_NULL(
                img = cpl_image_new(x, y, CPL_TYPE_FLOAT));
            KMO_TRY_EXIT_IF_ERROR(
                cpl_imagelist_set(cube, img, i));
        }
    }
    KMO_CATCH
    {
    }
}

/**
    @brief Fills a cube with data either serial or gaussian data.

    @param   x      The 1st dimension.
    @param   y      The 2nd dimension.
    @param   z      The 3rd dimension.
    @param   gauss  TRUE if images should contain a gauss, FALSE otherwise.

    @return  The generated imagelist.
 */
cpl_imagelist* kmo_test_create_cube(int x, int y, int z, int gauss, int *offset)
{
    cpl_imagelist   *imglist    = NULL;
    cpl_image       *img        = NULL;

    int             i           = 0;

    KMO_TRY
    {
        imglist = cpl_imagelist_new();
        KMO_TRY_EXIT_IF_NOT(imglist != NULL);

        for (i = 0; i < z; i++) {
            img = cpl_image_new(x, y, CPL_TYPE_FLOAT);
            KMO_TRY_EXIT_IF_NOT(img != NULL);

            if (gauss == FALSE) {
                kmo_test_fill_image(img, (*offset)++, test_global_seed_data);
            } else {
                KMO_TRY_EXIT_IF_ERROR(
                    cpl_image_fill_gaussian(img, x/2, y/2,
                                            *offset + test_global_seed_data,
                                            x/4, y/4));
            }

            cpl_imagelist_set(imglist, img, i);
        }
    }
    KMO_CATCH
    {
    }

    return imglist;
}
