/*
 * Copyright 2018-2019 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

/*
 * The OSA_USED macro can only be defined when the OSA component is used.
 * If the source code of the OSA component does not exist, the OSA_USED cannot be defined.
 * OR, If OSA component is not added into project event the OSA source code exists, the OSA_USED
 * also cannot be defined.
 * The source code path of the OSA component is <MCUXpresso_SDK>/components/osa.
 *
 */
#if defined(OSA_USED)
#if (defined(COMMON_TASK_ENABLE) && (COMMON_TASK_ENABLE > 0U))

#include "fsl_os_abstraction.h"

#include "fsl_component_common_task.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/
typedef struct _common_task_state
{
    OSA_TASK_HANDLE_DEFINE(commonTaskHandle);
    OSA_MSGQ_HANDLE_DEFINE(msgqhandle, COMMON_TASK_MAX_MSGQ_COUNT, sizeof(void *));
    uint8_t isInitialized;
} common_task_state_t;

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

void COMMON_TASK_task(osa_task_param_t param);

/*******************************************************************************
 * Variables
 ******************************************************************************/

extern const uint8_t gUseRtos_c;
static common_task_state_t s_commonTaskState[1];
OSA_TASK_DEFINE(COMMON_TASK_task, COMMON_TASK_PRIORITY, 1, COMMON_TASK_STACK_SIZE, false);

/*******************************************************************************
 * Code
 ******************************************************************************/

void COMMON_TASK_task(osa_task_param_t param)
{
    common_task_state_t *commonTaskStateHandle = (common_task_state_t *)param;
    common_task_message_t *msg;
    do
    {
        if (KOSA_StatusSuccess ==
            OSA_MsgQGet((osa_msgq_handle_t)commonTaskStateHandle->msgqhandle, &msg, osaWaitForever_c))
        {
            if (msg->callback)
            {
                msg->callback(msg->callbackParam);
            }
        }
    } while (gUseRtos_c);
}

common_task_status_t COMMON_TASK_init(void)
{
    osa_status_t status;

    if (s_commonTaskState->isInitialized)
    {
        return kStatus_COMMON_TASK_Error;
    }
    s_commonTaskState->isInitialized = 1U;

    status =
        OSA_MsgQCreate((osa_msgq_handle_t)s_commonTaskState->msgqhandle, COMMON_TASK_MAX_MSGQ_COUNT, sizeof(void *));
    assert(KOSA_StatusSuccess == status);

    status = OSA_TaskCreate((osa_task_handle_t)s_commonTaskState->commonTaskHandle, OSA_TASK(COMMON_TASK_task),
                            s_commonTaskState);
    assert(KOSA_StatusSuccess == status);
    (void)status;

    return kStatus_COMMON_TASK_Success;
}

common_task_status_t COMMON_TASK_deinit(void)
{
    if (!s_commonTaskState->isInitialized)
    {
        return kStatus_COMMON_TASK_Error;
    }

    OSA_MsgQDestroy((osa_msgq_handle_t)s_commonTaskState->msgqhandle);
    OSA_TaskDestroy((osa_task_handle_t)s_commonTaskState->commonTaskHandle);
    s_commonTaskState->isInitialized = 0U;

    return kStatus_COMMON_TASK_Success;
}

common_task_status_t COMMON_TASK_post_message(common_task_message_t *msg)
{
    assert(msg);
    assert(msg->callback);
    assert(s_commonTaskState->isInitialized);

    if (KOSA_StatusSuccess != OSA_MsgQPut((osa_msgq_handle_t)s_commonTaskState->msgqhandle, &msg))
    {
        return kStatus_COMMON_TASK_Error;
    }
    return kStatus_COMMON_TASK_Success;
}

void *COMMON_TASK_get_instance(void)
{
    return (void *)&s_commonTaskState[0];
}

int COMMON_TASK_get_pending_message_count(void)
{
    if (!s_commonTaskState->isInitialized)
    {
        return -1;
    }

    return OSA_MsgQAvailableMsgs((osa_msgq_handle_t)s_commonTaskState->msgqhandle);
}
#endif
#endif
