/*
 * Copyright (c) 2018 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <zephyr/kernel.h>
#include <errno.h>
#include <string.h>
#include <zephyr/posix/pthread.h>
#include <zephyr/sys/printk.h>
#include <zephyr/posix/signal.h>
#include <zephyr/posix/time.h>

#define ACTIVE 1
#define NOT_ACTIVE 0

static void zephyr_timer_wrapper(struct k_timer *ztimer);

struct timer_obj {
	struct k_timer ztimer;
	void (*sigev_notify_function)(union sigval val);
	union sigval val;
	int sigev_notify;
	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, 4);

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;
	}

	(timer->sigev_notify_function)(timer->val);
}

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

	while (1) {
		if (timer->reload == 0U) {
			timer->status = NOT_ACTIVE;
		}

		k_sem_take(&timer->sem_cond, K_FOREVER);

		(timer->sigev_notify_function)(timer->val);
	}

	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)
{
	struct timer_obj *timer;
	const k_timeout_t alloc_timeout = K_MSEC(CONFIG_TIMER_CREATE_WAIT);

	if (clockid != CLOCK_MONOTONIC || evp == NULL ||
	    (evp->sigev_notify != SIGEV_NONE &&
	     evp->sigev_notify != SIGEV_SIGNAL &&
	     evp->sigev_notify != SIGEV_THREAD)) {
		errno = EINVAL;
		return -1;
	}

	if (k_mem_slab_alloc(&posix_timer_slab, (void **)&timer, alloc_timeout) == 0) {
		(void)memset(timer, 0, sizeof(struct timer_obj));
	} else {
		errno = ENOMEM;
		return -1;
	}

	timer->sigev_notify_function = evp->sigev_notify_function;
	timer->val = evp->sigev_value;
	timer->interval.tv_sec = 0;
	timer->interval.tv_nsec = 0;
	timer->reload = 0U;
	timer->status = NOT_ACTIVE;

	if (evp->sigev_notify == SIGEV_NONE) {
		k_timer_init(&timer->ztimer, NULL, NULL);
	} else if (evp->sigev_notify == SIGEV_THREAD) {
		int ret;

		timer->sigev_notify = SIGEV_THREAD;
		k_sem_init(&timer->sem_cond, 0, 1);
		ret = pthread_create(&timer->thread, evp->sigev_notify_attributes,
							zephyr_thread_wrapper, timer);
		if (ret != 0) {
			k_mem_slab_free(&posix_timer_slab, (void *) &timer);
			return ret;
		}

		pthread_detach(timer->thread);
		k_timer_init(&timer->ztimer, zephyr_timer_interrupt, NULL);
	} else {
		k_timer_init(&timer->ztimer, zephyr_timer_wrapper, NULL);
	}

	*timerid = (timer_t)timer;

	return 0;
}

/**
 * @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->sigev_notify == SIGEV_THREAD)
		pthread_cancel(timer->thread);

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

	return 0;
}
