/*
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/types.h>
#include <zephyr/sys/byteorder.h>
#include <ztest.h>
#include "kconfig.h"

#define ULL_LLCP_UNITTEST

#include <zephyr/bluetooth/hci.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/slist.h>
#include <zephyr/sys/util.h>
#include "hal/ccm.h"

#include "util/util.h"
#include "util/mem.h"
#include "util/memq.h"
#include "util/dbuf.h"

#include "pdu.h"
#include "ll.h"
#include "ll_settings.h"

#include "lll.h"
#include "lll_df_types.h"
#include "lll_conn.h"
#include "ull_tx_queue.h"
#include "ull_conn_types.h"

#include "ull_llcp.h"
#include "ull_llcp_internal.h"
#include "ull_conn_internal.h"

#include "ll_feat.h"

#include "helper_pdu.h"
#include "helper_util.h"
#include "helper_features.h"

struct ll_conn *conn_from_pool;

static void setup(void)
{
	ull_conn_init();

	conn_from_pool = ll_conn_acquire();
	zassert_not_null(conn_from_pool, "Could not allocate connection memory", NULL);

	test_setup(conn_from_pool);
}

/*
 * +-----+                     +-------+            +-----+
 * | UT  |                     | LL_A  |            | LT  |
 * +-----+                     +-------+            +-----+
 *    |                            |                   |
 *    | Start                      |                   |
 *    | Feature Exchange Proc.     |                   |
 *    |--------------------------->|                   |
 *    |                            |                   |
 *    |                            | LL_FEATURE_REQ    |
 *    |                            |------------------>|
 *    |                            |                   |
 *    |                            |    LL_FEATURE_RSP |
 *    |                            |<------------------|
 *    |                            |                   |
 *    |     Feature Exchange Proc. |                   |
 *    |                   Complete |                   |
 *    |<---------------------------|                   |
 *    |                            |                   |
 */
void test_hci_feat_exchange_central_loc(void)
{
	uint64_t err;
	uint64_t set_featureset[] = {
		DEFAULT_FEATURE,
		DEFAULT_FEATURE };
	uint64_t rsp_featureset[] = { ((LL_FEAT_BIT_MASK_VALID & FEAT_FILTER_OCTET0) |
				       DEFAULT_FEATURE) &
					      LL_FEAT_BIT_MASK_VALID,
				      0x0 };
	int feat_to_test = ARRAY_SIZE(set_featureset);

	struct node_tx *tx;
	struct node_rx_pdu *ntf;

	struct pdu_data_llctrl_feature_req local_feature_req;
	struct pdu_data_llctrl_feature_rsp remote_feature_rsp;
	int feat_counter;
	uint16_t conn_handle;

	for (feat_counter = 0; feat_counter < feat_to_test; feat_counter++) {
		conn_handle = ll_conn_handle_get(conn_from_pool);

		sys_put_le64(set_featureset[feat_counter], local_feature_req.features);
		sys_put_le64(rsp_featureset[feat_counter], remote_feature_rsp.features);

		test_set_role(conn_from_pool, BT_HCI_ROLE_CENTRAL);
		/* Connect */
		ull_cp_state_set(conn_from_pool, ULL_CP_CONNECTED);

		/* Initiate a Feature Exchange Procedure via HCI */
		err = ll_feature_req_send(conn_handle);

		zassert_equal(err, BT_HCI_ERR_SUCCESS, "Error: %d", err);

		event_prepare(conn_from_pool);

		/* Tx Queue should have one LL Control PDU */
		lt_rx(LL_FEATURE_REQ, conn_from_pool, &tx, &local_feature_req);
		lt_rx_q_is_empty(conn_from_pool);

		/* Rx */
		lt_tx(LL_FEATURE_RSP, conn_from_pool, &remote_feature_rsp);

		event_done(conn_from_pool);
		/* There should be one host notification */

		ut_rx_pdu(LL_FEATURE_RSP, &ntf, &remote_feature_rsp);

		ut_rx_q_is_empty();

		zassert_equal(conn_from_pool->lll.event_counter, feat_counter + 1,
			      "Wrong event count %d\n", conn_from_pool->lll.event_counter);

		ull_cp_release_tx(conn_from_pool, tx);
		ull_cp_release_ntf(ntf);

		ll_conn_release(conn_from_pool);
	}
	zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt(),
				  "Free CTX buffers %d", ctx_buffers_free());
}

void test_hci_feat_exchange_wrong_handle(void)
{
	uint16_t conn_handle;
	uint64_t err;
	int ctx_counter;
	struct proc_ctx *ctx;

	conn_handle = ll_conn_handle_get(conn_from_pool);

	err = ll_feature_req_send(conn_handle + 1);

	zassert_equal(err, BT_HCI_ERR_UNKNOWN_CONN_ID, "Wrong reply for wrong handle\n");

	ctx_counter = 0;
	do {
		ctx = llcp_create_local_procedure(PROC_FEATURE_EXCHANGE);
		ctx_counter++;
	} while (ctx != NULL);

	zassert_equal(ctx_counter, CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM + 1,
				   "Error in setup of test\n");

	err = ll_feature_req_send(conn_handle);
	zassert_equal(err, BT_HCI_ERR_CMD_DISALLOWED, "Wrong reply for wrong handle\n");

	zassert_equal(ctx_buffers_free(), test_ctx_buffers_cnt() - (ctx_counter - 1),
		      "Free CTX buffers %d", ctx_buffers_free());
}

void test_hci_main(void)
{
	ztest_test_suite(hci_feat_exchange_central,
			 ztest_unit_test_setup_teardown(test_hci_feat_exchange_central_loc, setup,
							unit_test_noop),
			 ztest_unit_test_setup_teardown(test_hci_feat_exchange_wrong_handle,
							setup, unit_test_noop)

	);

	ztest_run_test_suite(hci_feat_exchange_central);
}
