/*
 * Copyright (C) 2020-2020 ikonke
 */



#include "kk_dm_queue.h"
#include "kk_tsl_common.h"


dm_queue_t g_dm_queue;

static dm_queue_t *_dm_queue_get_ctx(void)
{
    return &g_dm_queue;
}

static void _dm_queue_lock(void)
{
    dm_queue_t *ctx = _dm_queue_get_ctx();
    if (ctx->mutex) {
        HAL_MutexLock(ctx->mutex);
    }
}

static void _dm_queue_unlock(void)
{
    dm_queue_t *ctx = _dm_queue_get_ctx();
    if (ctx->mutex) {
        HAL_MutexUnlock(ctx->mutex);
    }
}

int dm_queue_init(int max_size)
{
    dm_queue_t *ctx = _dm_queue_get_ctx();

    memset(ctx, 0, sizeof(dm_queue_t));

    /* Create Mutex */
    ctx->mutex = HAL_MutexCreate();
    if (ctx->mutex == NULL) {
        return INVALID_PARAMETER;
    }

    /* Init List */
    ctx->msg_list.max_size = max_size;
    INIT_LIST_HEAD(&ctx->msg_list.message_list);

    return SUCCESS_RETURN;
}

void dm_queue_deinit(void)
{
    dm_queue_t *ctx = _dm_queue_get_ctx();
    dm_queue_msg_node_t *del_node = NULL;
    dm_queue_msg_node_t *next_node = NULL;
    dm_queue_msg_t *del_msg = NULL;

    if (ctx->mutex) {
        HAL_MutexDestroy(ctx->mutex);
    }

    list_for_each_entry_safe(del_node, next_node, &ctx->msg_list.message_list, linked_list, dm_queue_msg_node_t) {
        /* Free Message */
        del_msg = (dm_queue_msg_t *)del_node->data;
        if (del_msg->data) {
            free(del_msg->data);
        }
        free(del_msg);
        del_msg = NULL;

        /* Free Node */
        list_del(&del_node->linked_list);
        free(del_node);
    }
}

int dm_queue_msg_insert(void *data)
{
    dm_queue_t *ctx = _dm_queue_get_ctx();
    dm_queue_msg_node_t *node = NULL;

    if (data == NULL) {
        return INVALID_PARAMETER;
    }

    _dm_queue_lock();
    printf("dm msg list size: %d, max size: %d", ctx->msg_list.size, ctx->msg_list.max_size);
    if (ctx->msg_list.size >= ctx->msg_list.max_size) {
        printf("dm queue list full");
        _dm_queue_unlock();
        return FAIL_RETURN;
    }

    node = malloc(sizeof(dm_queue_msg_node_t));
    if (node == NULL) {
        _dm_queue_unlock();
        return DM_MEMORY_NOT_ENOUGH;
    }
    memset(node, 0, sizeof(dm_queue_msg_node_t));

    node->data = data;
    INIT_LIST_HEAD(&node->linked_list);
    ctx->msg_list.size++;
    list_add_tail(&node->linked_list, &ctx->msg_list.message_list);

    _dm_queue_unlock();
    return SUCCESS_RETURN;
}

int dm_queue_msg_next(void **data)
{
    dm_queue_t *ctx = _dm_queue_get_ctx();
    dm_queue_msg_node_t *node = NULL;

    if (data == NULL || *data != NULL) {
        return INVALID_PARAMETER;
    }

    _dm_queue_lock();

    if (list_empty(&ctx->msg_list.message_list)) {
        _dm_queue_unlock();
        return FAIL_RETURN;
    }

    node = list_first_entry(&ctx->msg_list.message_list, dm_queue_msg_node_t, linked_list);
    list_del(&node->linked_list);
    ctx->msg_list.size--;

    *data = node->data;
    free(node);

    _dm_queue_unlock();
    return SUCCESS_RETURN;
}

