/*
 * Copyright (C) 2023-2024 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 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 <birb.h>

/******************************************************************************
 * set tests
 *****************************************************************************/
static void
test_birb_date_time_set_null_null(void) {
	GDateTime *dt = NULL;
	g_assert_false(birb_date_time_set(&dt, NULL));
}

static void
test_birb_date_time_set_null_nonnull(void) {
	GDateTime *dt = NULL;
	GDateTime *dt1 = NULL;
	gboolean ret = FALSE;

	dt1 = g_date_time_new_now_utc();
	ret = birb_date_time_set(&dt, dt1);
	g_assert_true(ret);

	g_assert_true(dt == dt1);

	g_clear_pointer(&dt, g_date_time_unref);
	g_clear_pointer(&dt1, g_date_time_unref);
}

static void
test_birb_date_time_set_nonnull_null(void) {
	GDateTime *dt = NULL;
	gboolean ret = FALSE;

	dt = g_date_time_new_now_utc();
	ret = birb_date_time_set(&dt, NULL);
	g_assert_true(ret);

	g_assert_null(dt);
}

static void
test_birb_date_time_set_nonnull_nonnull(void) {
	GDateTime *tmp = NULL;
	GDateTime *dt = NULL;
	GDateTime *dt1 = NULL;
	gboolean ret = FALSE;

	/* We push our existing time back 2 hours to avoid issues with day light
	 * savings time and other weird clock skew issues.
	 */
	tmp = g_date_time_new_now_utc();
	dt = g_date_time_add_hours(tmp, -2);
	g_clear_pointer(&tmp, g_date_time_unref);

	dt1 = g_date_time_new_now_utc();

	ret = birb_date_time_set(&dt, dt1);
	g_assert_true(ret);

	g_assert_true(dt == dt1);

	g_clear_pointer(&dt, g_date_time_unref);
	g_clear_pointer(&dt1, g_date_time_unref);
}

/******************************************************************************
 * clear tests
 *****************************************************************************/
static void
test_birb_date_time_clear_null(void) {
	GDateTime *dt = NULL;

	birb_date_time_clear(NULL);
	birb_date_time_clear(&dt);

	g_assert_null(dt);
}

static void
test_birb_date_time_clear_nonnull(void) {
	GDateTime *dt = g_date_time_new_now_utc();

	birb_date_time_clear(&dt);

	g_assert_null(dt);
}

/******************************************************************************
 * compare tests
 *****************************************************************************/
static void
test_birb_date_time_compare_null(void) {
	GDateTime *dt = g_date_time_new_now_utc();
	gint result;

	result = birb_date_time_compare(dt, NULL);
	g_assert_cmpint(result, ==, 1);

	result = birb_date_time_compare(NULL, dt);
	g_assert_cmpint(result, ==, -1);

	result = birb_date_time_compare(NULL, NULL);
	g_assert_cmpint(result, ==, 0);

	g_date_time_unref(dt);
}

static void
test_birb_date_time_compare_nonnull(void) {
	GTimeZone *tz = g_time_zone_new_utc();
	GDateTime *now = g_date_time_new_now_utc();
	GDateTime *then1 = g_date_time_new_from_iso8601("1998-11-18T23:42:00", tz);
	GDateTime *then2 = g_date_time_new_utc(1998, 11, 18, 23, 42, 0.0);
	gint result;

	result = birb_date_time_compare(now, then1);
	g_assert_cmpint(result, ==, 1);

	result = birb_date_time_compare(then1, now);
	g_assert_cmpint(result, ==, -1);

	result = birb_date_time_compare(then1, then2);
	g_assert_cmpint(result, ==, 0);

	g_date_time_unref(now);
	g_date_time_unref(then1);
	g_date_time_unref(then2);
	g_time_zone_unref(tz);
}

/******************************************************************************
 * equal tests
 *****************************************************************************/
static void
test_birb_date_time_equal_null(void) {
	GDateTime *dt = g_date_time_new_now_utc();

	g_assert_false(birb_date_time_equal(dt, NULL));
	g_assert_false(birb_date_time_equal(NULL, dt));
	g_assert_true(birb_date_time_equal(NULL, NULL));

	g_date_time_unref(dt);
}

static void
test_birb_date_time_equal_nonnull(void) {
	GTimeZone *tz = g_time_zone_new_utc();
	GDateTime *now = g_date_time_new_now_utc();
	GDateTime *then1 = g_date_time_new_from_iso8601("1998-11-18T23:42:00", tz);
	GDateTime *then2 = g_date_time_new_utc(1998, 11, 18, 23, 42, 0.0);

	g_assert_true(birb_date_time_equal(then1, then2));
	g_assert_false(birb_date_time_equal(now, then2));
	g_assert_false(birb_date_time_equal(then1, now));

	g_date_time_unref(now);
	g_date_time_unref(then1);
	g_date_time_unref(then2);
	g_time_zone_unref(tz);
}

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

	g_test_add_func("/date-time/set/null-null",
	                test_birb_date_time_set_null_null);
	g_test_add_func("/date-time/set/null-nonnull",
	                test_birb_date_time_set_null_nonnull);
	g_test_add_func("/date-time/set/nonnull-null",
	                test_birb_date_time_set_nonnull_null);
	g_test_add_func("/date-time/set/nonnull-nonnull",
	                test_birb_date_time_set_nonnull_nonnull);

	g_test_add_func("/date-time/clear/null", test_birb_date_time_clear_null);
	g_test_add_func("/date-time/clear/nonnull",
	                test_birb_date_time_clear_nonnull);

	g_test_add_func("/date-time/compare/null", test_birb_date_time_compare_null);
	g_test_add_func("/date-time/compare/nonnull",
	                test_birb_date_time_compare_nonnull);

	g_test_add_func("/date-time/equal/null", test_birb_date_time_equal_null);
	g_test_add_func("/date-time/equal/nonnull",
	                test_birb_date_time_equal_nonnull);

	return g_test_run();
}
