/*
 * Copyright (C) Birb Developers
 *
 * Birb is the legal property of its developers, whose names are too numerous
 * to list here. Please refer to the AUTHORS file distributed with this source
 * distribution
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation; either version 2.1 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 Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
 */

#include <birb.h>

/******************************************************************************
 * Tests
 *****************************************************************************/
static void
test_birb_string_list_new(void) {
	BirbStringList *list = NULL;

	list = birb_string_list_new();
	birb_assert_type(list, BIRB_TYPE_STRING_LIST);
	g_assert_true(G_IS_LIST_MODEL(list));

	g_assert_finalize_object(list);
}

static void
test_birb_string_list_properties(void) {
	BirbStringList *list = NULL;
	GType item_type = G_TYPE_INVALID;
	guint n_items = 0;

	list = g_object_new(BIRB_TYPE_STRING_LIST,
	                    NULL);

	g_object_get(G_OBJECT(list),
	             "item-type", &item_type,
	             "n-items", &n_items,
	             NULL);

	g_assert_cmpuint(item_type, ==, BIRB_TYPE_STRING_OBJECT);

	g_assert_cmpuint(n_items, ==, 0);

	g_assert_finalize_object(list);
}

static void
test_birb_string_list_add_remove(void) {
	BirbStringList *list = NULL;
	BirbStringObject *obj = NULL;
	guint counter = 0;
	gboolean success = FALSE;

	list = birb_string_list_new();
	birb_count_list_model_items_changed(G_LIST_MODEL(list), &counter);

	birb_assert_list_model_n_items(list, 0);

	/* Add an item. */
	counter = 0;
	birb_string_list_append(list, "foo");
	g_assert_cmpuint(counter, ==, 1);
	birb_assert_list_model_n_items(list, 1);

	obj = g_list_model_get_item(G_LIST_MODEL(list), 0);
	birb_assert_type(obj, BIRB_TYPE_STRING_OBJECT);
	g_assert_cmpstr(birb_string_object_get_string(obj), ==, "foo");
	g_clear_object(&obj);

	/* Add another item. */
	counter = 0;
	birb_string_list_append(list, "bar");
	g_assert_cmpuint(counter, ==, 1);
	birb_assert_list_model_n_items(list, 2);

	obj = g_list_model_get_item(G_LIST_MODEL(list), 1);
	birb_assert_type(obj, BIRB_TYPE_STRING_OBJECT);
	g_assert_cmpstr(birb_string_object_get_string(obj), ==, "bar");
	g_clear_object(&obj);

	/* Remove the first item. */
	counter = 0;
	success = birb_string_list_remove(list, "foo");
	g_assert_true(success);
	g_assert_cmpuint(counter, ==, 1);
	birb_assert_list_model_n_items(list, 1);

	obj = g_list_model_get_item(G_LIST_MODEL(list), 0);
	birb_assert_type(obj, BIRB_TYPE_STRING_OBJECT);
	g_assert_cmpstr(birb_string_object_get_string(obj), ==, "bar");
	g_clear_object(&obj);

	/* Attempt to remove a non-existent item. */
	counter = 0;
	success = birb_string_list_remove(list, "baz");
	g_assert_false(success);
	g_assert_cmpuint(counter, ==, 0);
	birb_assert_list_model_n_items(list, 1);

	/* Clean up. */
	g_assert_finalize_object(list);
}

static void
test_birb_string_list_equal_nulls(void) {
	BirbStringList *list = NULL;

	g_assert_true(birb_string_list_equal(NULL, NULL));

	list = birb_string_list_new();

	g_assert_false(birb_string_list_equal(list, NULL));
	g_assert_false(birb_string_list_equal(NULL, list));

	g_assert_finalize_object(list);
}

static void
test_birb_string_list_equal_different_sizes(void) {
	BirbStringList *list1 = NULL;
	BirbStringList *list2 = NULL;

	list1 = birb_string_list_new();
	birb_string_list_append(list1, "foo");

	list2 = birb_string_list_new();

	g_assert_false(birb_string_list_equal(list1, list2));

	g_assert_finalize_object(list1);
	g_assert_finalize_object(list2);
}

static void
test_birb_string_list_equal_different_items(void) {
	BirbStringList *list1 = NULL;
	BirbStringList *list2 = NULL;

	list1 = birb_string_list_new();
	birb_string_list_append(list1, "foo");

	list2 = birb_string_list_new();
	birb_string_list_append(list2, "bar");

	g_assert_false(birb_string_list_equal(list1, list2));

	g_assert_finalize_object(list1);
	g_assert_finalize_object(list2);
}

static void
test_birb_string_list_equal_same_items(void) {
	BirbStringList *list1 = NULL;
	BirbStringList *list2 = NULL;

	list1 = birb_string_list_new();
	birb_string_list_append(list1, "foo");

	list2 = birb_string_list_new();
	birb_string_list_append(list2, "foo");

	g_assert_true(birb_string_list_equal(list1, list2));

	g_assert_finalize_object(list1);
	g_assert_finalize_object(list2);
}

static void
test_birb_string_list_equal_same_items_different_order(void) {
	BirbStringList *list1 = NULL;
	BirbStringList *list2 = NULL;

	list1 = birb_string_list_new();
	birb_string_list_append(list1, "foo");
	birb_string_list_append(list1, "bar");

	list2 = birb_string_list_new();
	birb_string_list_append(list2, "bar");
	birb_string_list_append(list2, "foo");

	g_assert_false(birb_string_list_equal(list1, list2));

	g_assert_finalize_object(list1);
	g_assert_finalize_object(list2);
}

/******************************************************************************
 * Main
 *****************************************************************************/
int
main(int argc, char *argv[]) {
	g_test_init(&argc, &argv, NULL);

	g_test_add_func("/birb/string-list/new", test_birb_string_list_new);
	g_test_add_func("/birb/string-list/properties",
	                test_birb_string_list_properties);

	g_test_add_func("/birb/string-list/add-remove",
	                test_birb_string_list_add_remove);

	g_test_add_func("/birb/string-list/equal/nulls",
	                test_birb_string_list_equal_nulls);
	g_test_add_func("/birb/string-list/equal/different-sizes",
	                test_birb_string_list_equal_different_sizes);
	g_test_add_func("/birb/string-list/equal/different-items",
	                test_birb_string_list_equal_different_items);
	g_test_add_func("/birb/string-list/equal/same-items",
	                test_birb_string_list_equal_same_items);
	g_test_add_func("/birb/string-list/equal/same-items-different-order",
	                test_birb_string_list_equal_same_items_different_order);

	return g_test_run();
}
