/*
 * Purple - Internet Messaging Library
 * Copyright (C) Pidgin Developers <devel@pidgin.im>
 *
 * Purple is the legal property of its developers, whose names are too numerous
 * to list here.  Please refer to the COPYRIGHT 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 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, see <https://www.gnu.org/licenses/>.
 */

#include <glib.h>

#include <birb.h>

#include <purple.h>

/******************************************************************************
 * Tests
 *****************************************************************************/
static void
test_purple_request_field_choice_new(void) {
	PurpleRequestField *field = NULL;

	field = purple_request_field_choice_new("id", "label");
	birb_assert_type(field, PURPLE_TYPE_REQUEST_FIELD_CHOICE);
	g_assert_true(G_IS_LIST_MODEL(field));

	g_assert_finalize_object(field);
}

static void
test_purple_request_field_choice_properties(void) {
	PurpleRequestField *field = NULL;
	BirbLocalizedString *selected_item;
	GType item_type = G_TYPE_INVALID;
	char *id = NULL;
	char *label = NULL;
	guint n_items = 0;
	guint selected = 0;

	field = g_object_new(PURPLE_TYPE_REQUEST_FIELD_CHOICE,
	                     "id", "choice",
	                     "label", "Pepsi Challenge",
	                     NULL);

	g_object_get(G_OBJECT(field),
	             "id", &id,
	             "item-type", &item_type,
	             "label", &label,
	             "n-items", &n_items,
	             "selected", &selected,
	             "selected-item", &selected_item,
	             NULL);

	g_assert_cmpstr(id, ==, "choice");
	g_clear_pointer(&id, g_free);

	g_assert_cmpuint(item_type, ==, BIRB_TYPE_LOCALIZED_STRING);

	g_assert_cmpstr(label, ==, "Pepsi Challenge");
	g_clear_pointer(&label, g_free);

	g_assert_cmpuint(n_items, ==, 0);

	g_assert_cmpuint(selected, ==, G_MAXUINT);

	g_assert_null(selected_item);

	g_assert_finalize_object(field);
}

static void
test_purple_request_field_choice_add_remove(void) {
	PurpleRequestField *field = NULL;
	PurpleRequestFieldChoice *choice = NULL;
	BirbLocalizedString *str1 = NULL;
	BirbLocalizedString *str2 = NULL;
	guint counter = 0;
	gboolean removed = FALSE;

	/* Create our field and add our counters. */
	field = purple_request_field_choice_new("id", "Pepsi Challenge");
	choice = PURPLE_REQUEST_FIELD_CHOICE(field);
	birb_count_list_model_items_changed(G_LIST_MODEL(choice), &counter);

	/* Make sure the model is empty by default. */
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 0);

	/* Add a bunch of items. */
	counter = 0;
	purple_request_field_choice_add(choice, "pepsi", "Pepsi");
	g_assert_cmpuint(counter, ==, 1);
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 1);

	counter = 0;
	purple_request_field_choice_add(choice, "coca-cola", "Coca Cola");
	g_assert_cmpuint(counter, ==, 1);
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 2);

	counter = 0;
	purple_request_field_choice_add(choice, "rc", "Royal Crown");
	g_assert_cmpuint(counter, ==, 1);
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 3);

	counter = 0;
	str1 = birb_localized_string_new("shasta", "Shasta");
	purple_request_field_choice_add_item(choice, str1);
	g_assert_cmpuint(counter, ==, 1);
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 4);

	counter = 0;
	purple_request_field_choice_add(choice, "sprecher", "Sprecher");
	g_assert_cmpuint(counter, ==, 1);
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 5);

	counter = 0;
	purple_request_field_choice_add(choice, "jolt", "Jolt");
	g_assert_cmpuint(counter, ==, 1);
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 6);

	/* Attempt to remove non existent items. */
	counter = 0;
	removed = purple_request_field_choice_remove(choice, 10000);
	g_assert_false(removed);
	g_assert_cmpuint(counter, ==, 0);
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 6);

	str2 = birb_localized_string_new("slurm", "Slurm");
	counter = 0;
	removed = purple_request_field_choice_remove_item(choice, str2);
	g_assert_false(removed);
	g_assert_cmpuint(counter, ==, 0);
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 6);
	g_assert_finalize_object(str2);

	counter = 0;
	removed = purple_request_field_choice_remove_by_id(choice, "slurm");
	g_assert_false(removed);
	g_assert_cmpuint(counter, ==, 0);
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 6);

	/* Remove the last item. */
	counter = 0;
	removed = purple_request_field_choice_remove(choice, 5);
	g_assert_true(removed);
	g_assert_cmpuint(counter, ==, 1);
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 5);

	/* Remove the item that was added as a localized string. */
	counter = 0;
	removed = purple_request_field_choice_remove_item(choice, str1);
	g_assert_true(removed);
	g_assert_cmpuint(counter, ==, 1);
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 4);

	/* Remove by id. */
	counter = 0;
	removed = purple_request_field_choice_remove_by_id(choice, "sprecher");
	g_assert_true(removed);
	g_assert_cmpuint(counter, ==, 1);
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 3);

	/* Remove the first item. */
	counter = 0;
	removed = purple_request_field_choice_remove(choice, 0);
	g_assert_true(removed);
	g_assert_cmpuint(counter, ==, 1);
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 2);

	/* Clear everything. */
	counter = 0;
	purple_request_field_choice_clear(choice);
	g_assert_cmpuint(counter, ==, 1);
	birb_assert_list_model_n_items(G_LIST_MODEL(choice), 0);

	/* Clean up. */
	g_assert_finalize_object(field);
	g_assert_finalize_object(str1);
}

static void
test_purple_request_field_choice_selected(void) {
	PurpleRequestField *field = NULL;
	PurpleRequestFieldChoice *choice = NULL;
	guint selected = 0;

	field = purple_request_field_choice_new("id", "Pepsi Challenge");
	choice = PURPLE_REQUEST_FIELD_CHOICE(field);

	/* Make sure this returns G_MAXUINT if no items are in the list. */
	selected = purple_request_field_choice_get_selected(choice);
	g_assert_cmpuint(selected, ==, G_MAXUINT);

	/* Add some items. */
	purple_request_field_choice_add(choice, "pepsi", "Pepsi");
	purple_request_field_choice_add(choice, "coca-cola", "Coca Cola");
	purple_request_field_choice_add(choice, "rc", "Royal Crown");
	purple_request_field_choice_add(choice, "shasta", "Shasta");
	purple_request_field_choice_add(choice, "sprecher", "Sprecher");
	purple_request_field_choice_add(choice, "jolt", "Jolt");

	/* Select the third item and make sure it was selected. */
	purple_request_field_choice_set_selected(choice, 2);
	selected = purple_request_field_choice_get_selected(choice);
	g_assert_cmpuint(selected, ==, 2);

	/* Select an item out of bounds and make sure it doesn't update. */
	purple_request_field_choice_set_selected(choice, 1337);
	selected = purple_request_field_choice_get_selected(choice);
	g_assert_cmpuint(selected, ==, 2);

	/* Make another selection that's valid and make sure it worked. */
	purple_request_field_choice_set_selected(choice, 4);
	selected = purple_request_field_choice_get_selected(choice);
	g_assert_cmpuint(selected, ==, 4);

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

static void
test_purple_request_field_choice_selected_item(void) {
	PurpleRequestField *field = NULL;
	PurpleRequestFieldChoice *choice = NULL;
	BirbLocalizedString *selected_item = NULL;

	field = purple_request_field_choice_new("id", "Pepsi Challenge");
	choice = PURPLE_REQUEST_FIELD_CHOICE(field);

	/* Make sure this returns NULL if no items are in the list. */
	selected_item = purple_request_field_choice_get_selected_item(choice);
	g_assert_null(selected_item);

	/* Add some items. */
	purple_request_field_choice_add(choice, "pepsi", "Pepsi");
	purple_request_field_choice_add(choice, "coca-cola", "Coca Cola");
	purple_request_field_choice_add(choice, "rc", "Royal Crown");
	purple_request_field_choice_add(choice, "shasta", "Shasta");
	purple_request_field_choice_add(choice, "sprecher", "Sprecher");
	purple_request_field_choice_add(choice, "jolt", "Jolt");

	/* Select the third item and make sure it was selected. */
	purple_request_field_choice_set_selected(choice, 2);
	selected_item = purple_request_field_choice_get_selected_item(choice);
	birb_assert_type(selected_item, BIRB_TYPE_LOCALIZED_STRING);
	g_assert_cmpstr(birb_localized_string_get_id(selected_item), ==, "rc");

	/* Select an item out of bounds and make sure it doesn't update. */
	purple_request_field_choice_set_selected(choice, 1337);
	selected_item = purple_request_field_choice_get_selected_item(choice);
	birb_assert_type(selected_item, BIRB_TYPE_LOCALIZED_STRING);
	g_assert_cmpstr(birb_localized_string_get_id(selected_item), ==, "rc");

	/* Make another selection that's valid and make sure it worked. */
	purple_request_field_choice_set_selected(choice, 4);
	selected_item = purple_request_field_choice_get_selected_item(choice);
	birb_assert_type(selected_item, BIRB_TYPE_LOCALIZED_STRING);
	g_assert_cmpstr(birb_localized_string_get_id(selected_item), ==,
	                "sprecher");

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

/******************************************************************************
 * Public API
 *****************************************************************************/
int
main(int argc, char **argv) {
	g_test_init(&argc, &argv, NULL);
	g_test_set_nonfatal_assertions();

	g_test_add_func("/request/field/choice/new",
	                test_purple_request_field_choice_new);
	g_test_add_func("/request/field/choice/properties",
	                test_purple_request_field_choice_properties);

	g_test_add_func("/request/field/choice/add-remove",
	                test_purple_request_field_choice_add_remove);

	g_test_add_func("/request/field/choice/selected",
	                test_purple_request_field_choice_selected);

	g_test_add_func("/request/field/choice/selected-item",
	                test_purple_request_field_choice_selected_item);

	return g_test_run();
}
