/*
 *  $Id: spectra.c 28804 2025-11-05 11:59:04Z yeti-dn $
 *  Copyright (C) 2025 David Nečas (Yeti).
 *  E-mail: yeti@gwyddion.net.
 *
 *  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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "tests/testlibgwy.h"

void
spectra_assert_equal(GObject *object, GObject *reference)
{
    g_assert_true(GWY_IS_SPECTRA(object));
    g_assert_true(GWY_IS_SPECTRA(reference));

    GwySpectra *spectra = GWY_SPECTRA(object), *spectra_ref = GWY_SPECTRA(reference);
    g_assert_cmpint(gwy_spectra_get_n_spectra(spectra), ==, gwy_spectra_get_n_spectra(spectra_ref));
    g_assert_cmpstr(gwy_spectra_get_title(spectra), ==, gwy_spectra_get_title(spectra_ref));
    g_assert_cmpstr(gwy_spectra_get_spectrum_x_label(spectra), ==, gwy_spectra_get_spectrum_x_label(spectra_ref));
    g_assert_cmpstr(gwy_spectra_get_spectrum_y_label(spectra), ==, gwy_spectra_get_spectrum_y_label(spectra_ref));
    g_assert_true(gwy_unit_equal(gwy_spectra_get_unit_xy(spectra), gwy_spectra_get_unit_xy(spectra_ref)));
    guint nspectra = gwy_spectra_get_n_spectra(spectra_ref);
    for (guint k = 0; k < nspectra; k++) {
        gdouble x, y, xref, yref;
        gwy_spectra_getpos(spectra, k, &x, &y);
        gwy_spectra_getpos(spectra_ref, k, &xref, &yref);
        g_assert_cmpfloat(x, ==, xref);
        g_assert_cmpfloat(y, ==, yref);
        g_assert_cmpint(gwy_spectra_get_spectrum_selected(spectra, k),
                        ==,
                        gwy_spectra_get_spectrum_selected(spectra_ref, k));
        GwyLine *spec = gwy_spectra_get_spectrum(spectra, k);
        GwyLine *spec_ref = gwy_spectra_get_spectrum(spectra_ref, k);
        line_assert_equal(G_OBJECT(spec), G_OBJECT(spec_ref));
    }
}

void
test_spectra_basic(void)
{
    GwySpectra *spectra = gwy_spectra_new();
    g_assert_cmpint(gwy_spectra_get_n_spectra(spectra), ==, 0);

    gwy_spectra_set_title(spectra, "Title");
    gwy_spectra_set_spectrum_x_label(spectra, "Abscissa");
    gwy_spectra_set_spectrum_y_label(spectra, "Ordinate");
    g_assert_cmpstr(gwy_spectra_get_title(spectra), ==, "Title");
    g_assert_cmpstr(gwy_spectra_get_spectrum_x_label(spectra), ==, "Abscissa");
    g_assert_cmpstr(gwy_spectra_get_spectrum_y_label(spectra), ==, "Ordinate");

    g_assert_finalize_object(spectra);
}

void
test_spectra_curves(void)
{
    GwySpectra *spectra = gwy_spectra_new();

    static const gdouble curvedata[5] = {
        1.0, -1.0, G_PI, 6e6, 0.1235,
    };

    GwyLine *spectrum1 = gwy_line_new(3, 1.0, TRUE);
    GwyLine *spectrum2 = gwy_line_new(5, 2.0, FALSE);
    gwy_assign(gwy_line_get_data(spectrum2), curvedata, 5);

    gwy_spectra_add_spectrum(spectra, spectrum1, -1.0, 5.0);
    gwy_spectra_add_spectrum(spectra, spectrum2, 1.0, 2.0);

    g_assert_cmpint(gwy_spectra_get_n_spectra(spectra), ==, 2);
    g_assert_true(gwy_spectra_get_spectrum(spectra, 0) == spectrum1);
    g_assert_true(gwy_spectra_get_spectrum(spectra, 1) == spectrum2);

    gdouble x, y;
    gwy_spectra_getpos(spectra, 0, &x, &y);
    g_assert_cmpfloat(x, ==, -1.0);
    g_assert_cmpfloat(y, ==, 5.0);
    gwy_spectra_getpos(spectra, 1, &x, &y);
    g_assert_cmpfloat(x, ==, 1.0);
    g_assert_cmpfloat(y, ==, 2.0);

    gwy_spectra_setpos(spectra, 1, 10.0, 200.0);
    gwy_spectra_getpos(spectra, 1, &x, &y);
    g_assert_cmpfloat(x, ==, 10.0);
    g_assert_cmpfloat(y, ==, 200.0);

    gwy_spectra_remove_spectrum(spectra, 0);
    g_assert_cmpint(gwy_spectra_get_n_spectra(spectra), ==, 1);
    g_assert_true(gwy_spectra_get_spectrum(spectra, 0) == spectrum2);

    g_assert_finalize_object(spectra);
    /* Unref the individual spectra after the main object to check finalisation. */
    g_assert_finalize_object(spectrum2);
    g_assert_finalize_object(spectrum1);
}

static GwySpectra*
create_spectra_for_serialisation(void)
{
    GwySpectra *spectra = gwy_spectra_new();
    gwy_spectra_set_title(spectra, "Spectrum");
    gwy_spectra_set_spectrum_x_label(spectra, "Xi");
    gwy_spectra_set_spectrum_y_label(spectra, "Eta");
    gwy_unit_set_from_string(gwy_spectra_get_unit_xy(spectra), "m");

    return spectra;
}

static void
add_spectra_data_for_serialisation(GwySpectra *spectra)
{
    for (gint i = 0; i < 5; i++) {
        GwyLine *spectrum = gwy_line_new(5, 11.0, TRUE);
        gwy_unit_set_from_string(gwy_line_get_unit_x(spectrum), "s");
        gwy_unit_set_from_string(gwy_line_get_unit_y(spectrum), "V");
        gwy_spectra_add_spectrum(spectra, spectrum, sin(i), cos(1.6*i));
        g_object_unref(spectrum);
    }
}

void
test_spectra_serialization(void)
{
    GwySpectra *spectra = create_spectra_for_serialisation();
    serialize_object_and_back(G_OBJECT(spectra), spectra_assert_equal, FALSE, NULL);

    add_spectra_data_for_serialisation(spectra);
    serialize_object_and_back(G_OBJECT(spectra), spectra_assert_equal, FALSE, NULL);

    g_assert_finalize_object(spectra);
}

void
test_spectra_copy(void)
{
    GwySpectra *spectra = create_spectra_for_serialisation();
    serializable_test_copy(GWY_SERIALIZABLE(spectra), spectra_assert_equal);

    add_spectra_data_for_serialisation(spectra);
    serializable_test_copy(GWY_SERIALIZABLE(spectra), spectra_assert_equal);

    g_assert_finalize_object(spectra);
}

void
test_spectra_assign(void)
{
    GwySpectra *spectra = create_spectra_for_serialisation();
    serializable_test_assign(GWY_SERIALIZABLE(spectra), NULL, spectra_assert_equal);

    add_spectra_data_for_serialisation(spectra);
    serializable_test_assign(GWY_SERIALIZABLE(spectra), NULL, spectra_assert_equal);

    g_assert_finalize_object(spectra);
}

/* vim: set cin columns=120 tw=118 et ts=4 sw=4 cino=>1s,e0,n0,f0,{0,}0,^0,\:1s,=0,g1s,h0,t0,+1s,c3,(0,u0 : */
