/*
 * timeutils.c - time utility functions.
 *
 * Copyright (C) 2025 Genexis Sweden AB. All rights reserved.
 *
 * See LICENSE file for license related information.
 *
 */

#include "timeutils.h"

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

bool timestamp_less_than(const struct timespec *lhs, const struct timespec *rhs)
{
	if (lhs->tv_sec == rhs->tv_sec)
		return lhs->tv_nsec < rhs->tv_nsec;
	else
		return lhs->tv_sec < rhs->tv_sec;
}

bool timestamp_greater_than(const struct timespec *lhs, const struct timespec *rhs)
{
	return timestamp_less_than(rhs, lhs);
}

bool timestamp_greater_or_equal(const struct timespec *lhs, const struct timespec *rhs)
{
	return !timestamp_less_than(lhs, rhs);
}

bool timestamp_less_or_equal(const struct timespec *lhs, const struct timespec *rhs)
{
	return !timestamp_less_than(rhs, lhs);
}

char *time_to_timestamp(const time_t *t, char *tsp)
{
	char tmpbuf[64] = {0};
	struct tm res;
	char sign;
	long toff, toff_hour, toff_min;
	time_t tt;

	if (!tsp)
		return NULL;

	if (!t)
		/* use now */
		time(&tt);
	else
		tt = *t;

	/* E.g. "2019-02-11T06:42:31.23039-08:00" */

	localtime_r(&tt, &res);
	tzset();
	toff = timezone;
	sign = toff > 0 ? '-' : '+';
	toff *= -1L;

	toff_hour = toff / 3600;
	toff_min = (toff % 3600) / 60;

	snprintf(tmpbuf, sizeof(tmpbuf), "%04d-%02d-%02dT%02d:%02d:%02d%c%02ld:%02ld",
			 res.tm_year + 1900, res.tm_mon + 1, res.tm_mday,
			 res.tm_hour, res.tm_min, res.tm_sec,
			 sign, toff_hour, toff_min);

	snprintf(tsp, 64, "%s", tmpbuf);

	return tsp;
}

/* get time adjustment seconds (time(tzone) - time(UTC) secs) */
static long timestamp_get_off_sec(const char *tsp)
{
	char *tzone;
	int toff = 0, sign;
	int toff_hour, toff_min;

	/* Example timestamp: "2019-02-11T06:42:31-08:00" */

	tzone = strchr(tsp, '+');
	if (!tzone) {
		tzone = strrchr(tsp, '-'); /* last occurence */
		sign = -1L;
	} else {
		sign = 1L;
	}

	if (tzone) {
		int ret = 0;

		ret = sscanf(tzone+1, "%02d:%02d", &toff_hour, &toff_min);
		if (ret == 2) {
			toff = toff_hour * 3600 + toff_min * 60; // seconds
			toff *= -sign;
		}
	}

	return toff;
}

/* Returns time alligned to UTC+0 */
time_t timestamp_to_time(const char *tsp)
{
	struct tm tm_time;
	time_t res;

	/* Example timestamp: "2019-02-11T06:42:31-08:00" */
	memset(&tm_time, 0, sizeof(tm_time));
	strptime(tsp, "%Y-%m-%dT%H:%M:%S", &tm_time);

	tzset();
	res = mktime(&tm_time);

	/* Allign by toff to get UTC+0 */
	res += timestamp_get_off_sec(tsp);

	return res;
}
