/*
 *  $Id: gl-material.c 28135 2025-06-24 14:51:47Z 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
test_gl_material_edit(void)
{
    GwyGLMaterial *material = g_object_new(GWY_TYPE_GL_MATERIAL, NULL);
    GwyResource *resource = GWY_RESOURCE(material);

    gwy_resource_rename(resource, "Unstable");
    g_assert_cmpstr(gwy_resource_get_name(resource), ==, "Unstable");

    static const GwyRGBA ambient = { 0.1, 0.2, 0.3, 0.4 };
    static const GwyRGBA diffuse = { 0.15, 0.25, 0.35, 0.45 };
    static const GwyRGBA specular = { 0.6, 0.7, 0.8, 0.9 };
    static const GwyRGBA emission = { 0.81, 0.82, 0.83, 0.84 };
    gdouble shininess = 0.55;
    const GwyRGBA *color;

    gwy_gl_material_set_ambient(material, &ambient);
    gwy_gl_material_set_diffuse(material, &diffuse);
    gwy_gl_material_set_specular(material, &specular);
    gwy_gl_material_set_emission(material, &emission);
    gwy_gl_material_set_shininess(material, shininess);

    color = gwy_gl_material_get_ambient(material);
    g_assert_true(gwy_rgba_equal(color, &ambient));

    color = gwy_gl_material_get_diffuse(material);
    g_assert_true(gwy_rgba_equal(color, &diffuse));

    color = gwy_gl_material_get_specular(material);
    g_assert_true(gwy_rgba_equal(color, &specular));

    color = gwy_gl_material_get_emission(material);
    g_assert_true(gwy_rgba_equal(color, &emission));

    g_assert_cmpfloat(gwy_gl_material_get_shininess(material), ==, shininess);

    g_assert_finalize_object(material);
}

static void
gl_material_assert_equal(GObject *object, GObject *reference)
{
    g_assert_true(GWY_IS_GL_MATERIAL(object));
    g_assert_true(GWY_IS_GL_MATERIAL(reference));

    GwyGLMaterial *material = GWY_GL_MATERIAL(object), *material_ref = GWY_GL_MATERIAL(reference);
    const GwyRGBA *color, *color_ref;

    color = gwy_gl_material_get_ambient(material);
    color_ref = gwy_gl_material_get_ambient(material_ref);
    g_assert_true(gwy_rgba_equal(color, color_ref));

    color = gwy_gl_material_get_diffuse(material);
    color_ref = gwy_gl_material_get_diffuse(material_ref);
    g_assert_true(gwy_rgba_equal(color, color_ref));

    color = gwy_gl_material_get_specular(material);
    color_ref = gwy_gl_material_get_specular(material_ref);
    g_assert_true(gwy_rgba_equal(color, color_ref));

    color = gwy_gl_material_get_emission(material);
    color_ref = gwy_gl_material_get_emission(material_ref);
    g_assert_true(gwy_rgba_equal(color, color_ref));

    g_assert_cmpfloat(gwy_gl_material_get_shininess(material), ==, gwy_gl_material_get_shininess(material_ref));
}

static GwyGLMaterial*
create_gl_material_for_serialisation(void)
{
    static const GwyRGBA ambient = { 0.1, 0.2, 0.3, 0.4 };
    static const GwyRGBA diffuse = { 0.15, 0.25, 0.35, 0.45 };
    static const GwyRGBA specular = { 0.6, 0.7, 0.8, 0.9 };
    static const GwyRGBA emission = { 0.81, 0.82, 0.83, 0.84 };
    gdouble shininess = 0.55;

    GwyGLMaterial *material = g_object_new(GWY_TYPE_GL_MATERIAL, NULL);
    gwy_resource_rename(GWY_RESOURCE(material), "Name");
    gwy_gl_material_set_ambient(material, &ambient);
    gwy_gl_material_set_diffuse(material, &diffuse);
    gwy_gl_material_set_specular(material, &specular);
    gwy_gl_material_set_emission(material, &emission);
    gwy_gl_material_set_shininess(material, shininess);

    return material;
}

void
test_gl_material_serialization(void)
{
    GwyGLMaterial *material = create_gl_material_for_serialisation();
    GObject *reconstructed = serialize_object_and_back(G_OBJECT(material), gl_material_assert_equal, TRUE, NULL);
    g_assert_cmpstr(gwy_resource_get_name(GWY_RESOURCE(reconstructed)), ==, "Name");
    g_assert_true(gwy_resource_is_modifiable(GWY_RESOURCE(reconstructed)));
    g_assert_false(gwy_resource_is_managed(GWY_RESOURCE(reconstructed)));

    g_assert_finalize_object(reconstructed);
    g_assert_finalize_object(material);
}

void
test_gl_material_copy(void)
{
    GwyGLMaterial *material = create_gl_material_for_serialisation();
    GObject *copy = G_OBJECT(gwy_serializable_copy(GWY_SERIALIZABLE(material)));
    g_assert_cmpstr(gwy_resource_get_name(GWY_RESOURCE(copy)), ==, "Name");
    g_assert_true(gwy_resource_is_modifiable(GWY_RESOURCE(copy)));
    g_assert_false(gwy_resource_is_managed(GWY_RESOURCE(copy)));

    g_assert_finalize_object(copy);
    g_assert_finalize_object(material);
}

void
test_gl_material_assign(void)
{
    GwyGLMaterial *material = create_gl_material_for_serialisation();
    GObject *copy = g_object_new(GWY_TYPE_GL_MATERIAL, "name", "Different", NULL);
    gwy_serializable_assign(GWY_SERIALIZABLE(copy), GWY_SERIALIZABLE(material));
    // Name is unchanged. This is the documented behaviour.
    g_assert_cmpstr(gwy_resource_get_name(GWY_RESOURCE(copy)), ==, "Different");
    g_assert_true(gwy_resource_is_modifiable(GWY_RESOURCE(copy)));
    g_assert_false(gwy_resource_is_managed(GWY_RESOURCE(copy)));

    g_assert_finalize_object(copy);
    g_assert_finalize_object(material);
}

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