/*
 * Ibis - IRCv3 Library
 * Copyright (C) 2022-2025 Ibis Developers
 *
 * Ibis 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 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 <birb.h>

#include <ibis.h>

/******************************************************************************
 * Tests
 *****************************************************************************/
static void
test_ibis_chanmodes_new(void) {
	IbisChanmodes *chanmodes = NULL;
	IbisChanmodeType type = IBIS_CHANMODE_TYPE_UNKNOWN;

	chanmodes = ibis_chanmodes_new();

	birb_assert_type(chanmodes, IBIS_TYPE_CHANMODES);

	/* Verify that all of the RFC 1459 and RFC 2811 modes are there. */
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'a');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'a');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'b');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_A);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'I');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_A);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'i');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'k');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_B);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'l');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_C);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'm');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'n');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'o');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_B);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'p');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'q');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'r');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 's');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 't');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'v');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_B);

	type = ibis_chanmodes_get_chanmode_type(chanmodes, '!');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_UNKNOWN);

	g_assert_finalize_object(chanmodes);
}

static void
test_ibis_chanmodes_parse(void) {
	IbisChanmodes *chanmodes = NULL;
	IbisChanmodeType type = IBIS_CHANMODE_TYPE_UNKNOWN;

	chanmodes = ibis_chanmodes_parse("Ibe,k,fl,CEMRUimnstu", "qaohv");

	birb_assert_type(chanmodes, IBIS_TYPE_CHANMODES);

	/* These are in the order of the CHANMODES string above. */
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'I');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_A);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'b');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_A);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'e');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_A);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'k');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_B);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'f');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_C);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'l');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_C);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'C');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'E');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'M');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'R');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'U');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'i');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'm');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'n');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 's');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 't');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'u');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_D);

	/* Check the PREFIX modes. */
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'q');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_B);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'a');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_B);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'o');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_B);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'h');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_B);
	type = ibis_chanmodes_get_chanmode_type(chanmodes, 'v');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_B);

	/* Make sure an unknown returns unknown. */
	type = ibis_chanmodes_get_chanmode_type(chanmodes, '!');
	g_assert_cmpint(type, ==, IBIS_CHANMODE_TYPE_UNKNOWN);

	g_assert_finalize_object(chanmodes);
}

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

	g_test_set_nonfatal_assertions();

	g_test_add_func("/ibis/chanmodes/new", test_ibis_chanmodes_new);
	g_test_add_func("/ibis/chanmodes/parse", test_ibis_chanmodes_parse);

	return g_test_run();
}
