/*
 * Copyright (c) 2018 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <kernel_structs.h>
#include "wrapper.h"

#define DONT_CARE               (0)
#define NSEC_PER_MSEC           (NSEC_PER_USEC * USEC_PER_MSEC)

/**
 * @brief Set the specified Thread Flags of a thread.
 */
uint32_t osThreadFlagsSet(osThreadId_t thread_id, uint32_t flags)
{
	int key;
	struct cv2_thread *tid = (struct cv2_thread *)thread_id;

	if ((thread_id == NULL) || (is_cmsis_rtos_v2_thread(thread_id) == NULL)
	    || (flags & 0x80000000)) {
		return osFlagsErrorParameter;
	}

	key = irq_lock();
	tid->signal_results |= flags;
	irq_unlock(key);

	k_poll_signal_raise(&tid->poll_signal, DONT_CARE);

	return tid->signal_results;
}

/**
 * @brief Get the current Thread Flags of current running thread.
 */
uint32_t osThreadFlagsGet(void)
{
	struct cv2_thread *tid;

	if (k_is_in_isr()) {
		return 0;
	}

	tid = (struct cv2_thread *)osThreadGetId();
	if (tid == NULL) {
		return 0;
	} else {
		return tid->signal_results;
	}
}

/**
 * @brief Clear the specified Thread Flags of current running thread.
 */
uint32_t osThreadFlagsClear(uint32_t flags)
{
	struct cv2_thread *tid;
	int sig, key;

	if (k_is_in_isr()) {
		return osFlagsErrorUnknown;
	}

	if (flags & 0x80000000) {
		return osFlagsErrorParameter;
	}

	tid = (struct cv2_thread *)osThreadGetId();
	if (tid == NULL) {
		return osFlagsErrorUnknown;
	}

	key = irq_lock();
	sig = tid->signal_results;
	tid->signal_results &= ~(flags);
	irq_unlock(key);

	return sig;
}

/**
 * @brief Wait for one or more Thread Flags of the current running thread to
 *        become signalled.
 */
uint32_t osThreadFlagsWait(uint32_t flags, uint32_t options, uint32_t timeout)
{
	struct cv2_thread *tid;
	int retval, key;
	u32_t sig;
	u32_t time_delta_ms, timeout_ms = __ticks_to_ms(timeout);
	u64_t time_stamp_start, hwclk_cycles_delta, time_delta_ns;

	if (k_is_in_isr()) {
		return osFlagsErrorUnknown;
	}

	if (flags & 0x80000000) {
		return osFlagsErrorParameter;
	}

	tid = (struct cv2_thread *)osThreadGetId();
	if (tid == NULL) {
		return osFlagsErrorUnknown;
	}

	for (;;) {

		time_stamp_start = (u64_t)k_cycle_get_32();

		switch (timeout) {
		case 0:
			retval = k_poll(&tid->poll_event, 1, K_NO_WAIT);
			break;
		case osWaitForever:
			retval = k_poll(&tid->poll_event, 1, K_FOREVER);
			break;
		default:
			retval = k_poll(&tid->poll_event, 1, timeout_ms);
			break;
		}

		switch (retval) {
		case 0:
			break;
		case -EAGAIN:
			return osFlagsErrorTimeout;
		default:
			return osFlagsErrorUnknown;
		}

		__ASSERT(tid->poll_event.state == K_POLL_STATE_SIGNALED,
			 "event state not signalled!");
		__ASSERT(tid->poll_event.signal->signaled == 1U,
			 "event signaled is not 1");

		/* Reset the states to facilitate the next trigger */
		tid->poll_event.signal->signaled = 0U;
		tid->poll_event.state = K_POLL_STATE_NOT_READY;

		if (options & osFlagsWaitAll) {
			/* Check if all events we are waiting on have
			 * been signalled
			 */
			if ((tid->signal_results & flags) == flags) {
				break;
			}

			/* If we need to wait on more signals, we need to
			 * adjust the timeout value accordingly based on
			 * the time that has already elapsed.
			 */
			hwclk_cycles_delta =
				(u64_t)k_cycle_get_32() - time_stamp_start;

			time_delta_ns =
				(u32_t)SYS_CLOCK_HW_CYCLES_TO_NS(hwclk_cycles_delta);

			time_delta_ms = (u32_t)time_delta_ns / NSEC_PER_MSEC;

			if (timeout_ms > time_delta_ms) {
				timeout_ms -= time_delta_ms;
			} else {
				timeout_ms = 0U;
			}
		} else {
			break;
		}
	}

	sig = tid->signal_results;
	if (!(options & osFlagsNoClear)) {

		/* Clear signal flags as the thread is ready now */
		key = irq_lock();
		tid->signal_results &= ~(flags);
		irq_unlock(key);
	}

	return sig;
}
