/*
 * Copyright (c) 2018 Intel Corporation
 * Copyright (c) 2024, Meta
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <errno.h>

#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/posix/pthread.h>
#include <zephyr/posix/signal.h>
#include <zephyr/posix/time.h>

#define ACTIVE 1
#define NOT_ACTIVE 0

LOG_MODULE_REGISTER(posix_timer);

static void zephyr_timer_wrapper(struct k_timer *ztimer);

struct timer_obj {
	struct k_timer ztimer;
	struct sigevent evp;
	struct k_sem sem_cond;
	pthread_t thread;
	struct timespec interval;	/* Reload value */
	uint32_t reload;			/* Reload value in ms */
	uint32_t status;
};

K_MEM_SLAB_DEFINE(posix_timer_slab, sizeof(struct timer_obj),
		  CONFIG_MAX_TIMER_COUNT, __alignof__(struct timer_obj));

static void zephyr_timer_wrapper(struct k_timer *ztimer)
{
	struct timer_obj *timer;

	timer = (struct timer_obj *)ztimer;

	if (timer->reload == 0U) {
		timer->status = NOT_ACTIVE;
		LOG_DBG("timer %p not active", timer);
		return;
	}

	if (timer->evp.sigev_notify == SIGEV_NONE) {
		LOG_DBG("SIGEV_NONE");
		return;
	}

	if (timer->evp.sigev_notify_function == NULL) {
		LOG_DBG("NULL sigev_notify_function");
		return;
	}

	LOG_DBG("calling sigev_notify_function %p", timer->evp.sigev_notify_function);
	(timer->evp.sigev_notify_function)(timer->evp.sigev_value);
}

static void *zephyr_thread_wrapper(void *arg)
{
	int ret;
	struct timer_obj *timer = (struct timer_obj *)arg;

	ret = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
	__ASSERT(ret == 0, "pthread_setcanceltype() failed: %d", ret);

	if (timer->evp.sigev_notify_attributes == NULL) {
		ret = pthread_detach(pthread_self());
		__ASSERT(ret == 0, "pthread_detach() failed: %d", ret);
	}

	while (1) {
		if (timer->reload == 0U) {
			timer->status = NOT_ACTIVE;
			LOG_DBG("timer %p not active", timer);
		}

		ret = k_sem_take(&timer->sem_cond, K_FOREVER);
		__ASSERT(ret == 0, "k_sem_take() failed: %d", ret);

		if (timer->evp.sigev_notify_function == NULL) {
			LOG_DBG("NULL sigev_notify_function");
			continue;
		}

		LOG_DBG("calling sigev_notify_function %p", timer->evp.sigev_notify_function);
		(timer->evp.sigev_notify_function)(timer->evp.sigev_value);
	}

	return NULL;
}

static void zephyr_timer_interrupt(struct k_timer *ztimer)
{
	struct timer_obj *timer;

	timer = (struct timer_obj *)ztimer;
	k_sem_give(&timer->sem_cond);
}

/**
 * @brief Create a per-process timer.
 *
 * This API does not accept SIGEV_THREAD as valid signal event notification
 * type.
 *
 * See IEEE 1003.1
 */
int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
{
	int ret = 0;
	int detachstate;
	struct timer_obj *timer;
	const k_timeout_t alloc_timeout = K_MSEC(CONFIG_TIMER_CREATE_WAIT);

	if (evp == NULL || timerid == NULL) {
		errno = EINVAL;
		return -1;
	}

	if (k_mem_slab_alloc(&posix_timer_slab, (void **)&timer, alloc_timeout) != 0) {
		LOG_DBG("k_mem_slab_alloc() failed: %d", ret);
		errno = ENOMEM;
		return -1;
	}

	*timer = (struct timer_obj){0};
	timer->evp = *evp;
	evp = &timer->evp;

	switch (evp->sigev_notify) {
	case SIGEV_NONE:
		k_timer_init(&timer->ztimer, NULL, NULL);
		break;
	case SIGEV_SIGNAL:
		k_timer_init(&timer->ztimer, zephyr_timer_wrapper, NULL);
		break;
	case SIGEV_THREAD:
		if (evp->sigev_notify_attributes != NULL) {
			ret = pthread_attr_getdetachstate(evp->sigev_notify_attributes,
							  &detachstate);
			if (ret != 0) {
				LOG_DBG("pthread_attr_getdetachstate() failed: %d", ret);
				errno = ret;
				ret = -1;
				goto free_timer;
			}

			if (detachstate != PTHREAD_CREATE_DETACHED) {
				ret = pthread_attr_setdetachstate(evp->sigev_notify_attributes,
								  PTHREAD_CREATE_DETACHED);
				if (ret != 0) {
					LOG_DBG("pthread_attr_setdetachstate() failed: %d", ret);
					errno = ret;
					ret = -1;
					goto free_timer;
				}
			}
		}

		ret = k_sem_init(&timer->sem_cond, 0, 1);
		if (ret != 0) {
			LOG_DBG("k_sem_init() failed: %d", ret);
			errno = -ret;
			ret = -1;
			goto free_timer;
		}

		ret = pthread_create(&timer->thread, evp->sigev_notify_attributes,
							zephyr_thread_wrapper, timer);
		if (ret != 0) {
			LOG_DBG("pthread_create() failed: %d", ret);
			errno = ret;
			ret = -1;
			goto free_timer;
		}

		k_timer_init(&timer->ztimer, zephyr_timer_interrupt, NULL);
		break;
	default:
		ret = -1;
		errno = EINVAL;
		goto free_timer;
	}

	*timerid = (timer_t)timer;
	goto out;

free_timer:
	k_mem_slab_free(&posix_timer_slab, (void *)&timer);

out:
	return ret;
}

/**
 * @brief Get amount of time left for expiration on a per-process timer.
 *
 * See IEEE 1003.1
 */
int timer_gettime(timer_t timerid, struct itimerspec *its)
{
	struct timer_obj *timer = (struct timer_obj *)timerid;
	int32_t remaining, leftover;
	int64_t   nsecs, secs;

	if (timer == NULL) {
		errno = EINVAL;
		return -1;
	}

	if (timer->status == ACTIVE) {
		remaining = k_timer_remaining_get(&timer->ztimer);
		secs =  remaining / MSEC_PER_SEC;
		leftover = remaining - (secs * MSEC_PER_SEC);
		nsecs = (int64_t)leftover * NSEC_PER_MSEC;
		its->it_value.tv_sec = (int32_t) secs;
		its->it_value.tv_nsec = (int32_t) nsecs;
	} else {
		/* Timer is disarmed */
		its->it_value.tv_sec = 0;
		its->it_value.tv_nsec = 0;
	}

	/* The interval last set by timer_settime() */
	its->it_interval = timer->interval;
	return 0;
}

/**
 * @brief Sets expiration time of per-process timer.
 *
 * See IEEE 1003.1
 */
int timer_settime(timer_t timerid, int flags, const struct itimerspec *value,
		  struct itimerspec *ovalue)
{
	struct timer_obj *timer = (struct timer_obj *) timerid;
	uint32_t duration, current;

	if (timer == NULL ||
	    value->it_interval.tv_nsec < 0 ||
	    value->it_interval.tv_nsec >= NSEC_PER_SEC ||
	    value->it_value.tv_nsec < 0 ||
	    value->it_value.tv_nsec >= NSEC_PER_SEC) {
		errno = EINVAL;
		return -1;
	}

	/*  Save time to expire and old reload value. */
	if (ovalue != NULL) {
		timer_gettime(timerid, ovalue);
	}

	/* Stop the timer if the value is 0 */
	if ((value->it_value.tv_sec == 0) && (value->it_value.tv_nsec == 0)) {
		if (timer->status == ACTIVE) {
			k_timer_stop(&timer->ztimer);
		}

		timer->status = NOT_ACTIVE;
		return 0;
	}

	/* Calculate timer period */
	timer->reload = _ts_to_ms(&value->it_interval);
	timer->interval.tv_sec = value->it_interval.tv_sec;
	timer->interval.tv_nsec = value->it_interval.tv_nsec;

	/* Calculate timer duration */
	duration = _ts_to_ms(&(value->it_value));
	if ((flags & TIMER_ABSTIME) != 0) {
		current = k_timer_remaining_get(&timer->ztimer);

		if (current >= duration) {
			duration = 0U;
		} else {
			duration -= current;
		}
	}

	if (timer->status == ACTIVE) {
		k_timer_stop(&timer->ztimer);
	}

	timer->status = ACTIVE;
	k_timer_start(&timer->ztimer, K_MSEC(duration), K_MSEC(timer->reload));
	return 0;
}

/**
 * @brief Returns the timer expiration overrun count.
 *
 * See IEEE 1003.1
 */
int timer_getoverrun(timer_t timerid)
{
	struct timer_obj *timer = (struct timer_obj *) timerid;

	if (timer == NULL) {
		errno = EINVAL;
		return -1;
	}

	int overruns = k_timer_status_get(&timer->ztimer) - 1;

	if (overruns > CONFIG_TIMER_DELAYTIMER_MAX) {
		overruns = CONFIG_TIMER_DELAYTIMER_MAX;
	}

	return overruns;
}

/**
 * @brief Delete a per-process timer.
 *
 * See IEEE 1003.1
 */
int timer_delete(timer_t timerid)
{
	struct timer_obj *timer = (struct timer_obj *) timerid;

	if (timer == NULL) {
		errno = EINVAL;
		return -1;
	}

	if (timer->status == ACTIVE) {
		timer->status = NOT_ACTIVE;
		k_timer_stop(&timer->ztimer);
	}

	if (timer->evp.sigev_notify == SIGEV_THREAD) {
		(void)pthread_cancel(timer->thread);
	}

	k_mem_slab_free(&posix_timer_slab, (void *)timer);

	return 0;
}
