/*
 *  $Id: graph-model.c 28514 2025-09-04 17:58:57Z 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
graph_model_assert_equal(GObject *object, GObject *reference)
{
    g_assert_true(GWY_IS_GRAPH_MODEL(object));
    g_assert_true(GWY_IS_GRAPH_MODEL(reference));

    GwyGraphModel *graph = GWY_GRAPH_MODEL(object), *graph_ref = GWY_GRAPH_MODEL(reference);
    g_assert_cmpint(gwy_graph_model_get_n_curves(graph), ==, gwy_graph_model_get_n_curves(graph_ref));
    assert_properties_equal(object, reference);
    guint n = gwy_graph_model_get_n_curves(graph_ref);
    for (guint i = 0; i < n; i++) {
        GwyGraphCurveModel *curve_ref = gwy_graph_model_get_curve(graph_ref, i);
        GwyGraphCurveModel *curve = gwy_graph_model_get_curve(graph, i);
        curve_model_assert_equal(G_OBJECT(curve), G_OBJECT(curve_ref));
    }
}

void
test_graph_model_basic(void)
{
    GwyGraphModel *graph = gwy_graph_model_new();

    g_object_set(graph,
                 "title", "This graph",
                 "x-min", -1.0,
                 "x-max", 2.0,
                 "x-min-set", TRUE,
                 "x-max-set", TRUE,
                 "axis-label-left", "Ordinate",
                 "axis-label-bottom", "Abscissa",
                 "y-logarithmic", TRUE,
                 NULL);

    gchar *title, *xlabel, *ylabel, *x2label, *y2label;
    gboolean xlog, ylog, xminset, xmaxset, yminset, ymaxset;
    gdouble xmin, xmax;

    g_object_get(graph,
                 "title", &title,
                 "x-min", &xmin,
                 "x-max", &xmax,
                 "x-min-set", &xminset,
                 "x-max-set", &xmaxset,
                 "y-min-set", &yminset,
                 "y-max-set", &ymaxset,
                 "axis-label-top", &x2label,
                 "axis-label-right", &y2label,
                 "axis-label-bottom", &xlabel,
                 "axis-label-left", &ylabel,
                 "x-logarithmic", &xlog,
                 "y-logarithmic", &ylog,
                 NULL);

    g_assert_cmpstr(title, ==, "This graph");
    g_assert_cmpstr(xlabel, ==, "Abscissa");
    g_assert_cmpstr(ylabel, ==, "Ordinate");
    g_assert_null(x2label);
    g_assert_null(y2label);
    g_assert_true(xminset);
    g_assert_true(xmaxset);
    g_assert_false(yminset);
    g_assert_false(ymaxset);
    g_assert_false(xlog);
    g_assert_true(ylog);
    g_free(title);
    g_free(xlabel);
    g_free(ylabel);
    g_free(x2label);
    g_free(y2label);

    g_assert_finalize_object(graph);
}

static GwyGraphModel*
create_graph_for_serialisation(void)
{
    GwyGraphModel *graph = gwy_graph_model_new();
    for (guint k = 0; k < 3; k++) {
        GwyGraphCurveModel *curve = gwy_graph_curve_model_new();
        gchar *name = g_strdup_printf("Curve #%u", k);
        g_object_set(curve, "description", name, NULL);
        g_free(name);

        gwy_graph_model_add_curve(graph, curve);
        guint n = k*(k + 1);
        if (n) {
            gdouble *xydata = g_new(gdouble, 2*n);
            for (guint i = 0; i < n; i++) {
                xydata[2*i] = sqrt(i+1.3*k) - G_PI;
                xydata[2*i + 1] = sin(4*i+k);
            }
            gwy_graph_curve_model_set_data_interleaved(curve, xydata, n);
            g_free(xydata);
        }
        g_object_unref(curve);
    }

    return graph;
}

static void
set_graph_properties_for_serialisation(GwyGraphModel *graph)
{
    g_object_set(graph,
                 "title", "This graph",
                 "y-min", -1.0,
                 "y-max", 2.0,
                 "y-min-set", TRUE,
                 "y-max-set", TRUE,
                 "axis-label-left", "Ordinate",
                 "axis-label-bottom", "Abscissa",
                 "x-logarithmic", TRUE,
                 NULL);

    gwy_unit_set_from_string(gwy_graph_model_get_unit_x(graph), "m");
    gwy_unit_set_from_string(gwy_graph_model_get_unit_y(graph), "V");
}

void
test_graph_model_serialization(void)
{
    GwyGraphModel *graph = create_graph_for_serialisation();
    serialize_object_and_back(G_OBJECT(graph), graph_model_assert_equal, FALSE, NULL);

    set_graph_properties_for_serialisation(graph);
    serialize_object_and_back(G_OBJECT(graph), graph_model_assert_equal, FALSE, NULL);

    g_assert_finalize_object(graph);
}

void
test_graph_model_copy(void)
{
    GwyGraphModel *graph = create_graph_for_serialisation();
    serializable_test_copy(GWY_SERIALIZABLE(graph), graph_model_assert_equal);

    set_graph_properties_for_serialisation(graph);
    serializable_test_copy(GWY_SERIALIZABLE(graph), graph_model_assert_equal);

    g_assert_finalize_object(graph);
}

void
test_graph_model_assign(void)
{
    GwyGraphModel *graph = create_graph_for_serialisation();
    serializable_test_assign(GWY_SERIALIZABLE(graph), NULL, graph_model_assert_equal);

    set_graph_properties_for_serialisation(graph);
    serializable_test_assign(GWY_SERIALIZABLE(graph), NULL, graph_model_assert_equal);

    /* TODO: Test assigning to a graph which already contains stuff. */

    g_assert_finalize_object(graph);
}

/* 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 : */
