/*
 *  $Id: resource.c 28791 2025-11-04 17:15:42Z 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"

#define GWY_RES_TEST_DEFAULT "Default"

#define GWY_TYPE_RES_TEST           (gwy_res_test_get_type())
#define GWY_RES_TEST(obj)           (G_TYPE_CHECK_INSTANCE_CAST((obj), GWY_TYPE_RES_TEST, GwyResTest))
#define GWY_IS_RES_TEST(obj)        (G_TYPE_CHECK_INSTANCE_TYPE((obj), GWY_TYPE_RES_TEST))
#define GWY_RES_TEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GWY_TYPE_RES_TEST, GwyResTestClass))

typedef struct _GwyResTest      GwyResTest;
typedef struct _GwyResTestClass GwyResTestClass;

struct _GwyResTestClass {
    GwyResourceClass parent_class;
};

struct _GwyResTest {
    GwyResource parent_instance;
    gint data;
};

/* Cannot make it static because we get it non-static automatically from the macro. */
GType gwy_res_test_get_type(void) G_GNUC_CONST;

static gpointer     resource_copy  (gpointer);
static void         resource_dump  (GwyResource *resource,
                                    GString *str);
static GwyResource* resource_parse (const gchar *text);
static GwyResTest*  create_res_test(const gchar *name,
                                    gint data,
                                    gboolean is_const);

static GwyResourceClass *parent_class = NULL;

G_DEFINE_TYPE(GwyResTest, gwy_res_test, GWY_TYPE_RESOURCE)

static void
gwy_res_test_class_init(GwyResTestClass *klass)
{
    GwyResourceClass *res_class = GWY_RESOURCE_CLASS(klass);

    parent_class = gwy_res_test_parent_class;

    res_class->item_type = *gwy_resource_class_get_item_type(parent_class);
    res_class->item_type.type = G_TYPE_FROM_CLASS(klass);
    res_class->item_type.copy = resource_copy;

    res_class->name = "restests";
    res_class->inventory = gwy_inventory_new(&res_class->item_type);
    gwy_inventory_set_default_item_name(res_class->inventory, GWY_RES_TEST_DEFAULT);
    res_class->dump = resource_dump;
    res_class->parse = resource_parse;
}

static void
gwy_res_test_init(GwyResTest *restest)
{
    restest->data = -1;
}

static gpointer
resource_copy(gpointer item)
{
    g_return_val_if_fail(GWY_IS_RES_TEST(item), NULL);
    GwyResTest *restest = create_res_test(gwy_resource_get_name(GWY_RESOURCE(item)),
                                          GWY_RES_TEST(item)->data,
                                          FALSE);
    return restest;
}

static void
resource_dump(GwyResource *resource, GString *str)
{
    g_string_append_printf(str, "%d\n", GWY_RES_TEST(resource)->data);
}

static GwyResource*
resource_parse(const gchar *text)
{
    gint data = 0;
    if (sscanf(text, "%d", &data) != 1)
        g_warning("Bad resource data %s.", text);
    GwyResTest *restest = create_res_test("", data, FALSE);
    return GWY_RESOURCE(restest);
}

static GwyResTest*
create_res_test(const gchar *name,
                gint data,
                gboolean is_const)
{
    GwyResTest *restest = g_object_new(GWY_TYPE_RES_TEST,
                                       "name", name,
                                       "const", is_const,
                                       NULL);
    restest->data = data;
    return restest;
}

static GwyResTest*
create_default(void)
{
    GwyResourceClass *klass = g_type_class_ref(GWY_TYPE_RES_TEST);
    GwyResTest *restest = create_res_test(GWY_RES_TEST_DEFAULT, 12345, TRUE);
    gwy_inventory_insert_item(klass->inventory, restest);
    g_object_unref(restest);
    g_type_class_unref(klass);
    return restest;
}

void
test_resource_default(void)
{
    GwyResTest *default_restest = create_default();
    GwyResourceClass *klass = g_type_class_peek(GWY_TYPE_RES_TEST);
    GwyInventory *inventory = gwy_resource_class_get_inventory(klass);

    GwyResource *restest = gwy_inventory_get_item_or_default(inventory, "Nonexistent");
    g_assert_true(restest == GWY_RESOURCE(default_restest));
    g_assert_false(gwy_resource_is_modifiable(restest));
    g_assert_false(gwy_resource_is_modified(restest));
    g_assert_true(gwy_resource_is_managed(restest));
    g_assert_cmpstr(gwy_resource_get_name(restest), ==, GWY_RES_TEST_DEFAULT);

    gwy_resource_classes_finalize();
}

void
test_resource_create_new(void)
{
    GwyResTest *default_restest = create_default();
    GwyResourceClass *klass = g_type_class_peek(GWY_TYPE_RES_TEST);
    GwyInventory *inventory = gwy_resource_class_get_inventory(klass);

    GwyResource *restest = gwy_inventory_new_item(inventory, NULL, "NewRes");
    g_assert_cmpint(GWY_RES_TEST(restest)->data, ==, 12345);
    GWY_RES_TEST(restest)->data = 6;
    g_assert_false(restest == GWY_RESOURCE(default_restest));
    g_assert_true(gwy_resource_is_modifiable(restest));
    g_assert_true(gwy_resource_is_modified(restest));
    g_assert_true(gwy_resource_is_managed(restest));
    g_assert_cmpstr(gwy_resource_get_name(restest), ==, "NewRes");

    g_assert_true(gwy_resource_class_mkdir(klass));
    g_assert_true(gwy_resource_save(restest, NULL));
    g_assert_false(gwy_resource_is_modified(restest));

    gwy_resource_classes_finalize();
}

void
test_resource_dump_parse(void)
{
    GwyResTest *restest = create_res_test("MyResTest", 706, FALSE);
    GwyResource *resource = GWY_RESOURCE(restest);
    restest->data = 706;
    g_assert_true(gwy_resource_is_modifiable(resource));
    g_assert_true(gwy_resource_is_modified(resource));
    g_assert_false(gwy_resource_is_managed(resource));
    g_assert_cmpstr(gwy_resource_get_name(resource), ==, "MyResTest");

    GwyResourceClass *klass = g_type_class_peek(GWY_TYPE_RES_TEST);
    GString *str = g_string_new(NULL);
    g_string_append_printf(str, "Gwyddion resource %s\n", g_type_name(GWY_TYPE_RES_TEST));
    klass->dump(resource, str);
    g_assert_true(gwy_resource_class_mkdir(klass));
    gchar *path = g_build_filename(ensure_test_data_dir(), "restests", "MyResTest", NULL);
    g_assert(g_file_set_contents(path, str->str, str->len, NULL));
    g_free(path);
    g_string_free(str, TRUE);

    gwy_resource_class_load(klass);
    GwyInventory *inventory = gwy_resource_class_get_inventory(klass);
    resource = gwy_inventory_get_item(inventory, "MyResTest");
    g_assert_nonnull(resource);
    g_assert_false(resource == GWY_RESOURCE(restest));
    g_assert(GWY_IS_RES_TEST(resource));
    g_assert_cmpint(GWY_RES_TEST(resource)->data, ==, 706);
    g_assert_true(gwy_resource_is_modifiable(resource));
    g_assert_false(gwy_resource_is_modified(resource));
    g_assert_true(gwy_resource_is_managed(resource));
    g_assert_cmpstr(gwy_resource_get_name(resource), ==, "MyResTest");

    gwy_resource_classes_finalize();
    g_object_unref(restest);
}

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