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

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

K_MEM_SLAB_DEFINE(cv2_event_flags_slab, sizeof(struct cv2_event_flags),
		  CONFIG_CMSIS_V2_EVT_FLAGS_MAX_COUNT, 4);

static const osEventFlagsAttr_t init_event_flags_attrs = {
	.name = "ZephyrEvent",
	.attr_bits = 0,
	.cb_mem = NULL,
	.cb_size = 0,
};

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

/**
 * @brief Create and Initialize an Event Flags object.
 */
osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr)
{
	struct cv2_event_flags *events;

	if (k_is_in_isr()) {
		return NULL;
	}

	if (attr == NULL) {
		attr = &init_event_flags_attrs;
	}

	if (k_mem_slab_alloc(&cv2_event_flags_slab, (void **)&events, 100)
	    == 0) {
		memset(events, 0, sizeof(struct cv2_event_flags));
	} else {
		return NULL;
	}

	k_poll_signal_init(&events->poll_signal);
	k_poll_event_init(&events->poll_event, K_POLL_TYPE_SIGNAL,
			  K_POLL_MODE_NOTIFY_ONLY, &events->poll_signal);
	events->signal_results = 0U;

	if (attr->name == NULL) {
		strncpy(events->name, init_event_flags_attrs.name,
			sizeof(events->name) - 1);
	} else {
		strncpy(events->name, attr->name, sizeof(events->name) - 1);
	}

	return (osEventFlagsId_t)events;
}

/**
 * @brief Set the specified Event Flags.
 */
uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags)
{
	struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;
	int key;

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

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

	k_poll_signal_raise(&events->poll_signal, DONT_CARE);

	return events->signal_results;
}

/**
 * @brief Clear the specified Event Flags.
 */
uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags)
{
	struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;
	int key;
	u32_t sig;

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

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

	return sig;
}

/**
 * @brief Wait for one or more Event Flags to become signaled.
 */
uint32_t osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags,
			  uint32_t options, uint32_t timeout)
{
	struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;
	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;

	/* Can be called from ISRs only if timeout is set to 0 */
	if (timeout > 0 && k_is_in_isr()) {
		return osFlagsErrorUnknown;
	}

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

	for (;;) {

		time_stamp_start = (u64_t)k_cycle_get_32();

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

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

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

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

		if (options & osFlagsWaitAll) {

			/* Check if all events we are waiting on have
			 * been signalled
			 */
			if ((events->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 = events->signal_results;
	if (!(options & osFlagsNoClear)) {

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

	return sig;
}

/**
 * @brief Get name of an Event Flags object.
 */
const char *osEventFlagsGetName(osEventFlagsId_t ef_id)
{
	struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;

	if (!k_is_in_isr() && (ef_id != NULL)) {
		return events->name;
	} else {
		return NULL;
	}
}

/**
 * @brief Get the current Event Flags.
 */
uint32_t osEventFlagsGet(osEventFlagsId_t ef_id)
{
	struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;

	if (ef_id == NULL) {
		return 0;
	}

	return events->signal_results;
}

/**
 * @brief Delete an Event Flags object.
 */
osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id)
{
	struct cv2_event_flags *events = (struct cv2_event_flags *)ef_id;

	if (ef_id == NULL) {
		return osErrorResource;
	}

	if (k_is_in_isr()) {
		return osErrorISR;
	}

	/* The status code "osErrorParameter" (the value of the parameter
	 * ef_id is incorrect) is not supported in Zephyr.
	 */

	k_mem_slab_free(&cv2_event_flags_slab, (void *)&events);

	return osOK;
}
