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

#include <zephyr/zephyr.h>
#include <stddef.h>
#include <ztest.h>

#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/sys/byteorder.h>
#include <host/hci_core.h>

#include <bt_conn_common.h>
#include "test_set_conn_cte_tx_params.h"

static uint16_t g_conn_handle;

static const uint8_t g_ant_ids[] = { 0x1, 0x2, 0x3, 0x4, 0x5 };

/**
 * @brief Structure to store CTE receive parameters for unit tests setup.
 */
struct ut_bt_df_conn_cte_tx_params {
	uint8_t cte_types;
	uint8_t switch_pattern_len;
	const uint8_t *ant_ids;
};

static struct ut_bt_df_conn_cte_tx_params g_params;

/* Macros delivering common values for unit tests */
#define CONN_HANDLE_INVALID (CONFIG_BT_MAX_CONN + 1)
#define ANTENNA_SWITCHING_SLOT_INVALID 0x3 /* BT_HCI_LE_ANTENNA_SWITCHING_SLOT_2US + 1 */
#define CTE_TYPE_NONE_ALLOWED 0x0 /* Any bit is not set */
#define CTE_TYPE_INVALID                                                                           \
	(~(uint8_t)(BT_HCI_LE_AOA_CTE_RSP | BT_HCI_LE_AOD_CTE_RSP_1US |                            \
		    BT_HCI_LE_AOD_CTE_RSP_2US)) /* Any other than allowed bit is set */

/* Antenna switch pattern length is stored in 1 octet. If BT Core spec. extends the max value to
 * UINT8_MAX expected failures may not be checked. If storage size is increased, tests shall be
 * updated.
 */
BUILD_ASSERT(CONFIG_BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN < UINT8_MAX,
	     "Can't test expected failures for switch pattern length longer or "
	     "equal to UINT8_MAX.");
#define SWITCH_PATTERN_LEN_TOO_LONG (CONFIG_BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN + 1)

BUILD_ASSERT(BT_HCI_LE_SWITCH_PATTERN_LEN_MIN > 0x0,
	     "Can't test expected failures for switch pattern length smaller or equal to zero.");
#define SWITCH_PATTERN_LEN_TOO_SHORT (BT_HCI_LE_SWITCH_PATTERN_LEN_MIN - 1)

static int send_set_conn_cte_tx_params(uint16_t conn_handle,
				       const struct ut_bt_df_conn_cte_tx_params *params)
{
	struct bt_hci_cp_le_set_conn_cte_tx_params *cp;
	uint8_t *dest_ant_ids;
	struct net_buf *buf;

	buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CONN_CTE_TX_PARAMS,
				sizeof(*cp) + params->switch_pattern_len);
	if (!buf) {
		return -ENOBUFS;
	}

	cp = net_buf_add(buf, sizeof(*cp));
	(void)memset(cp, 0, sizeof(*cp));

	cp->handle = sys_cpu_to_le16(conn_handle);
	cp->cte_types = params->cte_types;

	dest_ant_ids = net_buf_add(buf, params->switch_pattern_len);

	if (params->ant_ids) {
		(void)memcpy(dest_ant_ids, params->ant_ids, params->switch_pattern_len);
	}
	cp->switch_pattern_len = params->switch_pattern_len;

	return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_CONN_CTE_TX_PARAMS, buf, NULL);
}

void test_set_conn_cte_tx_params_with_invalid_conn_handle(void)
{
	int err;

	err = send_set_conn_cte_tx_params(CONN_HANDLE_INVALID, &g_params);
	zassert_equal(err, -EIO,
		      "Unexpected error value for set conn CTE tx params with wrong conn handle");
}

void test_set_conn_cte_tx_params_with_cte_type_none(void)
{
	int err;

	g_params.cte_types = CTE_TYPE_NONE_ALLOWED;

	err = send_set_conn_cte_tx_params(g_conn_handle, &g_params);
	zassert_equal(err, -EIO,
		      "Unexpected error value for set conn CTE TX params with invalid slot "
		      "durations");
}

void test_set_conn_cte_tx_params_with_cte_type_invalid(void)
{
	int err;

	g_params.cte_types = CTE_TYPE_INVALID;

	err = send_set_conn_cte_tx_params(g_conn_handle, &g_params);
	zassert_equal(err, -EIO,
		      "Unexpected error value for set conn CTE TX params with invalid slot "
		      "durations");
}

void test_set_conn_cte_tx_params_with_too_long_switch_pattern_len(void)
{
	int err;
	uint8_t ant_ids[SWITCH_PATTERN_LEN_TOO_LONG] = { 0 };

	g_params.switch_pattern_len = SWITCH_PATTERN_LEN_TOO_LONG;
	g_params.ant_ids = ant_ids;

	err = send_set_conn_cte_tx_params(g_conn_handle, &g_params);
	zassert_equal(err, -EIO,
		      "Unexpected error value for set conn CTE TX params with switch pattern set "
		      "length beyond max value");
}

void test_set_conn_cte_tx_params_with_too_short_switch_pattern_len(void)
{
	int err;
	uint8_t ant_ids[SWITCH_PATTERN_LEN_TOO_SHORT] = { 0 };

	g_params.switch_pattern_len = SWITCH_PATTERN_LEN_TOO_SHORT;
	g_params.ant_ids = &ant_ids[0];

	err = send_set_conn_cte_tx_params(g_conn_handle, &g_params);
	zassert_equal(err, -EIO,
		      "Unexpected error value for set conn CTE TX params with switch pattern set "
		      "length below min value");
}

void test_set_conn_cte_tx_params_with_ant_ids_ptr_null(void)
{
	int err;

	g_params.ant_ids = NULL;

	err = send_set_conn_cte_tx_params(g_conn_handle, &g_params);
	/* If size of the command buffer equals to expected value, controller is not able to
	 * identify wrong or missing antenna IDs. It will use provided values as if they were
	 * valid antenna IDs.
	 */
	zassert_equal(err, 0,
		      "Unexpected error value for set conn CTE TX params with antenna ids "
		      "pointing NULL");
}

void test_set_conn_cte_tx_params_with_correct_params(void)
{
	int err;

	err = send_set_conn_cte_tx_params(g_conn_handle, &g_params);
	zassert_equal(err, 0,
		      "Unexpected error value for set conn CTE TX params enabled with correct "
		      "params");
}

static void connection_setup(void)
{
	g_params.cte_types =
		BT_HCI_LE_AOA_CTE_RSP | BT_HCI_LE_AOD_CTE_RSP_1US | BT_HCI_LE_AOD_CTE_RSP_2US;
	g_params.switch_pattern_len = ARRAY_SIZE(g_ant_ids);
	g_params.ant_ids = g_ant_ids;

	g_conn_handle = ut_bt_create_connection();
}

static void connection_teardown(void)
{
	ut_bt_destroy_connection(g_conn_handle);
}

void run_set_conn_cte_tx_params_tests(void)
{
	ztest_test_suite(
		test_set_conn_cte_tx_params,
		ztest_unit_test(test_set_conn_cte_tx_params_with_invalid_conn_handle),
		ztest_unit_test_setup_teardown(test_set_conn_cte_tx_params_with_cte_type_none,
					       connection_setup, connection_teardown),
		ztest_unit_test_setup_teardown(test_set_conn_cte_tx_params_with_cte_type_invalid,
					       connection_setup, connection_teardown),
		ztest_unit_test_setup_teardown(
			test_set_conn_cte_tx_params_with_too_long_switch_pattern_len,
			connection_setup, connection_teardown),
		ztest_unit_test_setup_teardown(
			test_set_conn_cte_tx_params_with_too_short_switch_pattern_len,
			connection_setup, connection_teardown),
		ztest_unit_test_setup_teardown(test_set_conn_cte_tx_params_with_ant_ids_ptr_null,
					       connection_setup, connection_teardown),
		ztest_unit_test_setup_teardown(test_set_conn_cte_tx_params_with_correct_params,
					       connection_setup, connection_teardown));
	ztest_run_test_suite(test_set_conn_cte_tx_params);
}
