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



#include "kk_dm_queue.h"
#include "kk_tsl_common.h"
#include "kk_hal.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_lock2(void)
{
    dm_queue_t *ctx = _dm_queue_get_ctx();
    if (ctx->mutex2) {
        HAL_MutexLock(ctx->mutex2);
    }
}

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

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


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

static void _dm_queue_unlock3(void)
{
    dm_queue_t *ctx = _dm_queue_get_ctx();
    if (ctx->mutex3) {
        HAL_MutexUnlock(ctx->mutex3);
    }
}
static void _dm_queue_unlock4(void)
{
    dm_queue_t *ctx = _dm_queue_get_ctx();
    if (ctx->mutex4) {
        HAL_MutexUnlock(ctx->mutex4);
    }
}



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;
    }

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

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

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

    /* Init List */
    ctx->msg_list.max_size = max_size;
    INIT_LIST_HEAD(&ctx->msg_list.message_list);
    ctx->msg_list2.max_size = max_size;
    INIT_LIST_HEAD(&ctx->msg_list2.message_list);
    ctx->msg_list3.max_size = max_size;
    INIT_LIST_HEAD(&ctx->msg_list3.message_list);
    ctx->msg_list4.max_size = max_size;
    INIT_LIST_HEAD(&ctx->msg_list4.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);
    }

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

    if (ctx->mutex3) {
        HAL_MutexDestroy(ctx->mutex3);
    }
	
    if (ctx->mutex4) {
        HAL_MutexDestroy(ctx->mutex4);
    }

    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);
    }

    del_node = NULL;
    next_node = NULL;
    del_msg = NULL;
    list_for_each_entry_safe(del_node, next_node, &ctx->msg_list2.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);
    }

    del_node = NULL;
    next_node = NULL;
    del_msg = NULL;
    list_for_each_entry_safe(del_node, next_node, &ctx->msg_list3.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);
    }
    del_node = NULL;
    next_node = NULL;
    del_msg = NULL;
    list_for_each_entry_safe(del_node, next_node, &ctx->msg_list4.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();
    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 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;
}

int dm_queue_msg_insert2(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_lock2();
    if (ctx->msg_list2.size >= ctx->msg_list2.max_size) {
        printf("dm queue list full");
        _dm_queue_unlock2();
        return FAIL_RETURN;
    }

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

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

    _dm_queue_unlock2();
    return SUCCESS_RETURN;
}

int dm_queue_msg_next2(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_lock2();

    if (list_empty(&ctx->msg_list2.message_list)) {
        _dm_queue_unlock2();
        return FAIL_RETURN;
    }

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

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

    _dm_queue_unlock2();
    return SUCCESS_RETURN;
}


int dm_queue_msg_insert3(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_lock3();
    if (ctx->msg_list3.size >= ctx->msg_list3.max_size) {
        _dm_queue_unlock3();
        return FAIL_RETURN;
    }

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

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

    _dm_queue_unlock3();
    return SUCCESS_RETURN;
}

int dm_queue_msg_next3(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_lock3();

    if (list_empty(&ctx->msg_list3.message_list)) {
        _dm_queue_unlock3();
        return FAIL_RETURN;
    }

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

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

    _dm_queue_unlock3();
    return SUCCESS_RETURN;
}

int dm_queue_msg_insert4(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_lock4();
    printf("dm msg list size: %d, max size: %d", ctx->msg_list4.size, ctx->msg_list4.max_size);
    if (ctx->msg_list4.size >= ctx->msg_list4.max_size) {
        printf("dm queue list full");
        _dm_queue_unlock4();
        return FAIL_RETURN;
    }

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

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

    _dm_queue_unlock4();
    return SUCCESS_RETURN;
}

int dm_queue_msg_next4(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_lock4();

    if (list_empty(&ctx->msg_list4.message_list)) {
        _dm_queue_unlock4();
        return FAIL_RETURN;
    }

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

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

    _dm_queue_unlock4();
    return SUCCESS_RETURN;
}

