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

