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

#include <ztest.h>
#include <misc/slist.h>

static sys_slist_t test_list;

struct container_node {
	sys_snode_t node;
	int unused;
};

static struct container_node test_node_1;
static struct container_node test_node_2;
static struct container_node test_node_3;
static struct container_node test_node_4;

static inline bool verify_emptyness(sys_slist_t *list)
{
	sys_snode_t *node;
	sys_snode_t *s_node;
	struct container_node *cnode;
	struct container_node *s_cnode;
	int count;

	if (!sys_slist_is_empty(list)) {
		return false;
	}

	if (sys_slist_peek_head(list)) {
		return false;
	}

	if (sys_slist_peek_tail(list)) {
		return false;
	}

	count = 0;
	SYS_SLIST_FOR_EACH_NODE(list, node) {
		count++;
	}

	if (count) {
		return false;
	}

	SYS_SLIST_FOR_EACH_NODE_SAFE(list, node, s_node) {
		count++;
	}

	if (count) {
		return false;
	}

	count = 0;
	SYS_SLIST_FOR_EACH_CONTAINER(list, cnode, node) {
		count++;
	}

	if (count) {
		return false;
	}

	count = 0;
	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(list, cnode, s_cnode, node) {
		count++;
	}

	if (count) {
		return false;
	}

	return true;
}

static inline bool verify_content_amount(sys_slist_t *list, int amount)
{
	sys_snode_t *node;
	sys_snode_t *s_node;
	struct container_node *cnode;
	struct container_node *s_cnode;
	int count;

	if (sys_slist_is_empty(list)) {
		return false;
	}

	if (!sys_slist_peek_head(list)) {
		return false;
	}

	if (!sys_slist_peek_tail(list)) {
		return false;
	}

	count = 0;
	SYS_SLIST_FOR_EACH_NODE(list, node) {
		count++;
	}

	if (count != amount) {
		return false;
	}

	count = 0;
	SYS_SLIST_FOR_EACH_NODE_SAFE(list, node, s_node) {
		count++;
	}

	if (count != amount) {
		return false;
	}

	count = 0;
	SYS_SLIST_FOR_EACH_CONTAINER(list, cnode, node) {
		count++;
	}

	if (count != amount) {
		return false;
	}

	count = 0;
	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(list, cnode, s_cnode, node) {
		count++;
	}

	if (count != amount) {
		return false;
	}

	return true;
}

static inline bool verify_tail_head(sys_slist_t *list,
				    sys_snode_t *head,
				    sys_snode_t *tail,
				    bool same)
{
	if (sys_slist_peek_head(list) != head) {
		return false;
	}

	if (sys_slist_peek_tail(list) != tail) {
		return false;
	}

	if (same) {
		if (sys_slist_peek_head(list) != sys_slist_peek_tail(list)) {
			return false;
		}
	} else {
		if (sys_slist_peek_head(list) == sys_slist_peek_tail(list)) {
			return false;
		}
	}

	return true;
}

void slist_test(void)
{
	sys_slist_init(&test_list);

	zassert_true((verify_emptyness(&test_list)), "test_list should be empty");

	/* Appending node 1 */
	sys_slist_append(&test_list, &test_node_1.node);
	zassert_true((verify_content_amount(&test_list, 1)),
		    "test_list has wrong content");

	zassert_true((verify_tail_head(&test_list, &test_node_1.node,
				      &test_node_1.node, true)),
		    "test_list head/tail are wrong");

	/* Finding and removing node 1 */
	sys_slist_find_and_remove(&test_list, &test_node_1.node);
	zassert_true((verify_emptyness(&test_list)),
		    "test_list should be empty");

	/* Prepending node 1 */
	sys_slist_prepend(&test_list, &test_node_1.node);
	zassert_true((verify_content_amount(&test_list, 1)),
		    "test_list has wrong content");

	zassert_true((verify_tail_head(&test_list, &test_node_1.node,
				      &test_node_1.node, true)),
		    "test_list head/tail are wrong");

	/* Removing node 1 */
	sys_slist_remove(&test_list, NULL, &test_node_1.node);
	zassert_true((verify_emptyness(&test_list)),
		    "test_list should be empty");

	/* Appending node 1 */
	sys_slist_append(&test_list, &test_node_1.node);
	/* Prepending node 2 */
	sys_slist_prepend(&test_list, &test_node_2.node);

	zassert_true((verify_content_amount(&test_list, 2)),
		    "test_list has wrong content");

	zassert_true((verify_tail_head(&test_list, &test_node_2.node,
				      &test_node_1.node, false)),
		    "test_list head/tail are wrong");

	/* Appending node 3 */
	sys_slist_append(&test_list, &test_node_3.node);

	zassert_true((verify_content_amount(&test_list, 3)),
		    "test_list has wrong content");

	zassert_true((verify_tail_head(&test_list, &test_node_2.node,
				      &test_node_3.node, false)),
		    "test_list head/tail are wrong");

	zassert_true((sys_slist_peek_next(&test_node_2.node) ==
					 &test_node_1.node),
		    "test_list node links are wrong");

	/* Inserting node 4 after node 2 */
	sys_slist_insert(&test_list, &test_node_2.node, &test_node_4.node);

	zassert_true((verify_tail_head(&test_list, &test_node_2.node,
				      &test_node_3.node, false)),
		    "test_list head/tail are wrong");

	zassert_true((sys_slist_peek_next(&test_node_2.node) ==
					 &test_node_4.node),
		    "test_list node links are wrong");

	/* Finding and removing node 1 */
	sys_slist_find_and_remove(&test_list, &test_node_1.node);
	zassert_true((verify_content_amount(&test_list, 3)),
		    "test_list has wrong content");

	zassert_true((verify_tail_head(&test_list, &test_node_2.node,
				      &test_node_3.node, false)),
		    "test_list head/tail are wrong");

	/* Removing node 3 */
	sys_slist_remove(&test_list, &test_node_4.node, &test_node_3.node);
	zassert_true((verify_content_amount(&test_list, 2)),
		    "test_list has wrong content");

	zassert_true((verify_tail_head(&test_list, &test_node_2.node,
				      &test_node_4.node, false)),
		    "test_list head/tail are wrong");

	/* Removing node 4 */
	sys_slist_remove(&test_list, &test_node_2.node, &test_node_4.node);
	zassert_true((verify_content_amount(&test_list, 1)),
		    "test_list has wrong content");

	zassert_true((verify_tail_head(&test_list, &test_node_2.node,
				      &test_node_2.node, true)),
		    "test_list head/tail are wrong");

	/* Removing node 2 */
	sys_slist_remove(&test_list, NULL, &test_node_2.node);
	zassert_true((verify_emptyness(&test_list)),
		    "test_list should be empty");

	/* test iterator from a node */
	struct data_node {
		sys_snode_t node;
		int data;
	} data_node[6] = {
		{ .data = 0 },
		{ .data = 1 },
		{ .data = 2 },
		{ .data = 3 },
		{ .data = 4 },
		{ .data = 5 },
	};
	sys_snode_t *node = NULL;
	int ii;

	sys_slist_init(&test_list);

	for (ii = 0; ii < 6; ii++) {
		sys_slist_append(&test_list, &data_node[ii].node);
	}

	ii = 0;
	SYS_SLIST_ITERATE_FROM_NODE(&test_list, node) {
		ii++;
		if (((struct data_node *)node)->data == 2) {
			break;
		}
	}
	zassert_equal(ii, 3, "");

	ii = 0;
	SYS_SLIST_ITERATE_FROM_NODE(&test_list, node) {
		ii++;
		if (((struct data_node *)node)->data == 3) {
			break;
		}
	}
	zassert_equal(ii, 1, "");

	ii = 0;
	SYS_SLIST_ITERATE_FROM_NODE(&test_list, node) {
		ii++;
	}
	zassert_equal(ii, 2, "");
}
