/*
 * Ibis - IRCv3 Library
 * Copyright (C) 2022-2024 Ibis Developers
 *
 * This library 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 of the License, or (at your option) any later version.
 *
 * This library 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 library; if not, see <https://www.gnu.org/licenses/>.
 */

#include <glib.h>
#include <glib/gi18n.h>

#include <ibis.h>

/******************************************************************************
 * Tests
 *****************************************************************************/
static void
test_ibis_client_properties(void) {
	IbisCapabilities *capabilities = NULL;
	IbisClient *client = NULL;
	IbisFeatures *features = NULL;
	GCancellable *cancellable = NULL;
	GError *error = NULL;
	char *alt_nick = NULL;
	char *nick = NULL;
	char *realname = NULL;
	char *username = NULL;
	gboolean connected = FALSE;

	client = g_object_new(
		IBIS_TYPE_CLIENT,
		"alt-nick", "nick1",
		"nick", "nick",
		"realname", "realname",
		"username", "username",
		NULL);

	g_object_get(
		G_OBJECT(client),
		"alt-nick", &alt_nick,
		"cancellable", &cancellable,
		"capabilities", &capabilities,
		"connected", &connected,
		"error", &error,
		"features", &features,
		"nick", &nick,
		"realname", &realname,
		"username", &username,
		NULL);

	g_assert_cmpstr(alt_nick, ==, "nick1");
	g_clear_pointer(&alt_nick, g_free);

	g_assert_null(cancellable);

	g_assert_true(IBIS_IS_CAPABILITIES(capabilities));
	g_clear_object(&capabilities);

	g_assert_false(connected);

	g_assert_no_error(error);

	g_assert_true(IBIS_IS_FEATURES(features));
	g_clear_object(&features);

	g_assert_cmpstr(nick, ==, "nick");
	g_clear_pointer(&nick, g_free);

	g_assert_cmpstr(realname, ==, "realname");
	g_clear_pointer(&realname, g_free);

	g_assert_cmpstr(username, ==, "username");
	g_clear_pointer(&username, g_free);

	g_assert_finalize_object(client);
}

static void
test_ibis_client_alt_nick(void) {
	IbisClient *client = NULL;
	const char *alt_nick = NULL;

	client = ibis_client_new();

	ibis_client_set_alt_nick(client, "alt");
	alt_nick = ibis_client_get_alt_nick(client);
	g_assert_cmpstr(alt_nick, ==, "alt");

	ibis_client_set_alt_nick(client, NULL);
	alt_nick = ibis_client_get_alt_nick(client);
	g_assert_null(alt_nick);

	ibis_client_set_alt_nick(client, "");
	alt_nick = ibis_client_get_alt_nick(client);
	g_assert_cmpstr(alt_nick, ==, "");

	g_assert_finalize_object(client);
}

static void
test_ibis_client_realname_null(void) {
	IbisClient *client = NULL;
	const char *realname = NULL;

	client = ibis_client_new();

	ibis_client_set_realname(client, "realname");
	realname = ibis_client_get_realname(client);
	g_assert_cmpstr(realname, ==, "realname");

	ibis_client_set_realname(client, NULL);
	realname = ibis_client_get_realname(client);
	g_assert_null(realname);

	g_assert_finalize_object(client);
}

static void
test_ibis_client_realname_empty(void) {
	if(g_test_subprocess()) {
		IbisClient *client = NULL;

		client = ibis_client_new();
		ibis_client_set_realname(client, "");

		g_assert_finalize_object(client);
	}

	g_test_trap_subprocess(NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
	g_test_trap_assert_stderr("*realname[0] != '\\0'*");
}

static void
test_ibis_client_username_null(void) {
	IbisClient *client = NULL;
	const char *username = NULL;

	client = ibis_client_new();

	ibis_client_set_username(client, "username");
	username = ibis_client_get_username(client);
	g_assert_cmpstr(username, ==, "username");

	ibis_client_set_username(client, NULL);
	username = ibis_client_get_username(client);
	g_assert_null(username);

	g_assert_finalize_object(client);
}

static void
test_ibis_client_username_empty(void) {
	if(g_test_subprocess()) {
		IbisClient *client = NULL;

		client = ibis_client_new();
		ibis_client_set_username(client, "");

		g_assert_finalize_object(client);
	}

	g_test_trap_subprocess(NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
	g_test_trap_assert_stderr("*username[0] != '\\0'*");
}

static void
test_ibis_client_is_channel_default(void) {
	IbisClient *client = NULL;

	client = ibis_client_new();

	g_assert_true(ibis_client_is_channel(client, "#foo"));
	g_assert_false(ibis_client_is_channel(client, "&bar"));
	g_assert_false(ibis_client_is_channel(client, "baz"));

	g_assert_finalize_object(client);
}

static void
test_ibis_client_is_channel_custom(void) {
	IbisClient *client = NULL;
	IbisFeatures *features = NULL;
	IbisMessage *message = NULL;

	client = ibis_client_new();
	features = ibis_client_get_features(client);

	message = ibis_message_new(IBIS_RPL_ISUPPORT);
	ibis_message_set_params(message, IBIS_FEATURE_CHANTYPES "=#&", NULL);
	ibis_features_parse(features, message);
	g_assert_finalize_object(message);

	g_assert_true(ibis_client_is_channel(client, "#foo"));
	g_assert_true(ibis_client_is_channel(client, "&bar"));
	g_assert_false(ibis_client_is_channel(client, "baz"));

	g_assert_finalize_object(client);
}

static void
test_ibis_client_network_default(void) {
	IbisClient *client = NULL;
	const char *network = NULL;

	client = ibis_client_new();

	network = ibis_client_get_network(client);
	g_assert_null(network);

	g_assert_finalize_object(client);
}

static void
test_ibis_client_network_custom(void) {
	IbisClient *client = NULL;
	IbisFeatures *features = NULL;
	IbisMessage *message = NULL;
	const char *network = NULL;

	client = ibis_client_new();
	features = ibis_client_get_features(client);

	message = ibis_message_new(IBIS_RPL_ISUPPORT);
	ibis_message_set_params(message, IBIS_FEATURE_NETWORK "=unit-test", NULL);
	ibis_features_parse(features, message);
	g_assert_finalize_object(message);

	network = ibis_client_get_network(client);
	g_assert_cmpstr(network, ==, "unit-test");

	g_assert_finalize_object(client);
}

static void
test_ibis_client_normalize_null(void) {
	IbisClient *client = NULL;
	char *normalized = NULL;

	client = ibis_client_new();

	normalized = ibis_client_normalize(client, "Foo[]🐻\\Baz~");
	g_assert_cmpstr(normalized, ==, "Foo[]🐻\\Baz~");
	g_free(normalized);

	g_assert_finalize_object(client);
}

static void
test_ibis_client_normalize_ascii(void) {
	IbisClient *client = NULL;
	IbisFeatures *features = NULL;
	IbisMessage *message = NULL;
	char *normalized = NULL;

	client = ibis_client_new();
	features = ibis_client_get_features(client);

	message = ibis_message_new(IBIS_RPL_ISUPPORT);
	ibis_message_set_params(message, IBIS_FEATURE_CASEMAPPING "=ascii", NULL);
	ibis_features_parse(features, message);
	g_assert_finalize_object(message);

	normalized = ibis_client_normalize(client, "Foo[]🐻\\Baz~");
	g_assert_cmpstr(normalized, ==, "foo[]🐻\\baz~");
	g_free(normalized);

	g_assert_finalize_object(client);
}

static void
test_ibis_client_normalize_rfc1459(void) {
	IbisClient *client = NULL;
	IbisFeatures *features = NULL;
	IbisMessage *message = NULL;
	char *normalized = NULL;

	client = ibis_client_new();
	features = ibis_client_get_features(client);

	message = ibis_message_new(IBIS_RPL_ISUPPORT);
	ibis_message_set_params(message, IBIS_FEATURE_CASEMAPPING "=rfc1459", NULL);
	ibis_features_parse(features, message);
	g_assert_finalize_object(message);

	normalized = ibis_client_normalize(client, "Foo[]🐻\\Baz~");
	g_assert_cmpstr(normalized, ==, "foo{}🐻|baz^");
	g_free(normalized);

	g_assert_finalize_object(client);
}

static void
test_ibis_client_normalize_rfc1459_strict(void) {
	IbisClient *client = NULL;
	IbisFeatures *features = NULL;
	IbisMessage *message = NULL;
	char *normalized = NULL;

	client = ibis_client_new();
	features = ibis_client_get_features(client);

	message = ibis_message_new(IBIS_RPL_ISUPPORT);
	ibis_message_set_params(message, IBIS_FEATURE_CASEMAPPING "=rfc1459-strict", NULL);
	ibis_features_parse(features, message);
	g_assert_finalize_object(message);

	normalized = ibis_client_normalize(client, "Foo[]🐻\\Baz~");
	g_assert_cmpstr(normalized, ==, "foo{}🐻|baz~");
	g_free(normalized);

	g_assert_finalize_object(client);
}

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

	g_test_set_nonfatal_assertions();

	g_test_add_func("/ibis/client/properties", test_ibis_client_properties);

	g_test_add_func("/ibis/client/alt-nick",
	                test_ibis_client_alt_nick);

	g_test_add_func("/ibis/client/realname/null",
	                test_ibis_client_realname_null);
	g_test_add_func("/ibis/client/realname/empty",
	                test_ibis_client_realname_empty);

	g_test_add_func("/ibis/client/username/null",
	                test_ibis_client_username_null);
	g_test_add_func("/ibis/client/username/empty",
	                test_ibis_client_username_empty);

	g_test_add_func("/ibis/client/is-channel/default",
	                test_ibis_client_is_channel_default);
	g_test_add_func("/ibis/client/is-channel/custom",
	                test_ibis_client_is_channel_custom);

	g_test_add_func("/ibis/client/network/default",
	                test_ibis_client_network_default);
	g_test_add_func("/ibis/client/network/custom",
	                test_ibis_client_network_custom);

	g_test_add_func("/ibis/client/normalize/null",
	                test_ibis_client_normalize_null);
	g_test_add_func("/ibis/client/normalize/ascii",
	                test_ibis_client_normalize_ascii);
	g_test_add_func("/ibis/client/normalize/rfc1459",
	                test_ibis_client_normalize_rfc1459);
	g_test_add_func("/ibis/client/normalize/rfc1459-strict",
	                test_ibis_client_normalize_rfc1459_strict);

	return g_test_run();
}
