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

#include <zephyr/kernel.h>
#include <string.h>
#include "wrapper.h"

K_MEM_SLAB_DEFINE(cv2_msgq_slab, sizeof(struct cv2_msgq),
		  CONFIG_CMSIS_V2_MSGQ_MAX_COUNT, 4);

static const osMessageQueueAttr_t init_msgq_attrs = {
	.name = "ZephyrMsgQ",
	.attr_bits = 0,
	.cb_mem = NULL,
	.cb_size = 0,
	.mq_mem = NULL,
	.mq_size = 0,
};

/**
 * @brief Create and Initialize Message queue.
 */
osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size,
				     const osMessageQueueAttr_t *attr)
{
	struct cv2_msgq *msgq;

	BUILD_ASSERT(CONFIG_HEAP_MEM_POOL_SIZE >=
		     CONFIG_CMSIS_V2_MSGQ_MAX_DYNAMIC_SIZE,
		     "heap must be configured to be at least the max dynamic size");

	if (k_is_in_isr()) {
		return NULL;
	}

	if ((attr != NULL) && (attr->mq_size < msg_count * msg_size)) {
		return NULL;
	}

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

	if (k_mem_slab_alloc(&cv2_msgq_slab, (void **)&msgq, K_MSEC(100)) == 0) {
		(void)memset(msgq, 0, sizeof(struct cv2_msgq));
	} else {
		return NULL;
	}

	if (attr->mq_mem == NULL) {
		__ASSERT((msg_count * msg_size) <=
			 CONFIG_CMSIS_V2_MSGQ_MAX_DYNAMIC_SIZE,
			 "message queue size exceeds dynamic maximum");

		msgq->pool = k_calloc(msg_count, msg_size);
		if (msgq->pool == NULL) {
			k_mem_slab_free(&cv2_msgq_slab, (void *) &msgq);
			return NULL;
		}
		msgq->is_dynamic_allocation = TRUE;
	} else {
		msgq->pool = attr->mq_mem;
		msgq->is_dynamic_allocation = FALSE;
	}

	k_msgq_init(&msgq->z_msgq, msgq->pool, msg_size, msg_count);

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

	return (osMessageQueueId_t)(msgq);
}

/**
 * @brief Put a message to a Queue.
 */
osStatus_t osMessageQueuePut(osMessageQueueId_t msgq_id, const void *msg_ptr,
			     uint8_t msg_prio, uint32_t timeout)
{
	struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;
	int retval;

	ARG_UNUSED(msg_prio);

	if (msgq == NULL) {
		return osErrorParameter;
	}

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

	if (timeout == 0U) {
		retval = k_msgq_put(&msgq->z_msgq, (void *)msg_ptr, K_NO_WAIT);
	} else if (timeout == osWaitForever) {
		retval = k_msgq_put(&msgq->z_msgq, (void *)msg_ptr, K_FOREVER);
	} else {
		retval = k_msgq_put(&msgq->z_msgq, (void *)msg_ptr,
				    K_TICKS(timeout));
	}

	if (retval == 0) {
		return osOK;
	} else if (retval == -EAGAIN) {
		return osErrorTimeout;
	} else {
		return osErrorResource;
	}
}

/**
 * @brief Get a message or Wait for a Message from a Queue.
 */
osStatus_t osMessageQueueGet(osMessageQueueId_t msgq_id, void *msg_ptr,
			     uint8_t *msg_prio, uint32_t timeout)
{
	struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;
	int retval;

	ARG_UNUSED(msg_prio);

	if (msgq == NULL) {
		return osErrorParameter;
	}

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

	if (timeout == 0U) {
		retval = k_msgq_get(&msgq->z_msgq, msg_ptr, K_NO_WAIT);
	} else if (timeout == osWaitForever) {
		retval = k_msgq_get(&msgq->z_msgq, msg_ptr, K_FOREVER);
	} else {
		retval = k_msgq_get(&msgq->z_msgq, msg_ptr,
				    K_TICKS(timeout));
	}

	if (retval == 0) {
		return osOK;
	} else if (retval == -EAGAIN) {
		return osErrorTimeout;
	} else if (retval == -ENOMSG) {
		return osErrorResource;
	}

	return osOK;
}

/**
 * @brief Get maximum number of messages in a Message Queue.
 */
uint32_t osMessageQueueGetCapacity(osMessageQueueId_t msgq_id)
{
	struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;

	if (msgq == NULL) {
		return 0;
	} else {
		return msgq->z_msgq.max_msgs;
	}
}

/**
 * @brief Get maximum message size in a Message Queue.
 */
uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t msgq_id)
{
	struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;

	if (msgq == NULL) {
		return 0;
	} else {
		return msgq->z_msgq.msg_size;
	}
}

/**
 * @brief Get number of queued messages in a Message Queue.
 */
uint32_t osMessageQueueGetCount(osMessageQueueId_t msgq_id)
{
	struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;

	if (msgq == NULL) {
		return 0;
	} else {
		return k_msgq_num_used_get(&msgq->z_msgq);
	}
}

/**
 * @brief Get number of available slots for messages in a Message Queue.
 */
uint32_t osMessageQueueGetSpace(osMessageQueueId_t msgq_id)
{
	struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;

	if (msgq == NULL) {
		return 0;
	} else {
		return k_msgq_num_free_get(&msgq->z_msgq);
	}
}

/**
 * @brief Get name of a Message Queue object.
 */
const char *osMessageQueueGetName(osMessageQueueId_t msgq_id)
{
	struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;

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

/**
 * @brief Reset a Message Queue to initial empty state.
 */
osStatus_t osMessageQueueReset(osMessageQueueId_t msgq_id)
{
	struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;

	if (msgq == NULL) {
		return osErrorParameter;
	}

	if (k_is_in_isr()) {
		return osErrorISR;
	}

	/* The status code "osErrorResource" (the message queue specified by
	 * parameter msgq_id is in an invalid message queue state) is not
	 * supported in Zephyr.
	 */

	k_msgq_purge(&msgq->z_msgq);

	return osOK;
}

/**
 * @brief Delete a Message Queue object.
 */
osStatus_t osMessageQueueDelete(osMessageQueueId_t msgq_id)
{
	struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;

	if (msgq == NULL) {
		return osErrorParameter;
	}

	if (k_is_in_isr()) {
		return osErrorISR;
	}

	/* The status code "osErrorResource" (the message queue specified by
	 * parameter msgq_id is in an invalid message queue state) is not
	 * supported in Zephyr.
	 */

	if (msgq->is_dynamic_allocation) {
		k_free(msgq->pool);
	}
	k_mem_slab_free(&cv2_msgq_slab, (void *)&msgq);

	return osOK;
}
