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

#include <argparse.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/settings/settings.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/bluetooth/bluetooth.h>

#include "testlib/adv.h"
#include "testlib/att_read.h"
#include "testlib/att_write.h"
#include "bs_macro.h"
#include "bs_sync.h"
#include <testlib/conn.h>
#include "testlib/log_utils.h"
#include "testlib/scan.h"
#include "testlib/security.h"

/* This test uses system asserts to fail tests. */
BUILD_ASSERT(__ASSERT_ON);

#define CENTRAL_DEVICE_NBR    0
#define PERIPHERAL_DEVICE_NBR 1

LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);

#define UUID_1                                                                                     \
	BT_UUID_DECLARE_128(0xdb, 0x1f, 0xe2, 0x52, 0xf3, 0xc6, 0x43, 0x66, 0xb3, 0x92, 0x5d,      \
			    0xc6, 0xe7, 0xc9, 0x59, 0x9d)

#define UUID_2                                                                                     \
	BT_UUID_DECLARE_128(0x3f, 0xa4, 0x7f, 0x44, 0x2e, 0x2a, 0x43, 0x05, 0xab, 0x38, 0x07,      \
			    0x8d, 0x16, 0xbf, 0x99, 0xf1)

static ssize_t read_mtu_validation_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr,
					void *buf, uint16_t buf_len, uint16_t offset)
{
	ssize_t read_len;

	LOG_INF("Server side buf_len %u", buf_len);

	/* Note: We assume `buf_len` is equal to the usable payload
	 * capacity of the response PDU. I.e. `(ATT_MTU - 1)` for
	 * BT_ATT_OP_READ_RSP and BT_ATT_OP_READ_BLOB_RSP.
	 */

	/* Send back a full PDU on the first read (on offset 0). Then an
	 * not full one for the second read to conlude the long read..
	 */
	read_len = buf_len;
	if (offset > 0) {
		__ASSERT_NO_MSG(read_len > 0);
		/* The second PDU is one-less-than-full to test for off
		 * by one errors.
		 */
		read_len -= 1;
	}

	/* If the ATT_MTU is too large, sending a one-less-than-full
	 * response would exeed the max attribute length limit.
	 */
	__ASSERT(buf_len < (BT_ATT_MAX_ATTRIBUTE_LEN / 2),
		 "The EATT buffer is too large for this test.");

	/* Ensure the padding bytes (that are not overwritten later in
	 * this function) are initialized.
	 */
	memset(buf, 0, read_len);

	/* Echo back the requested read size in the first two bytes of
	 * each read.
	 */
	__ASSERT_NO_MSG(read_len >= 2);
	sys_put_le16(read_len, buf);

	return read_len;
}

static struct bt_gatt_attr attrs[] = {
	BT_GATT_PRIMARY_SERVICE(UUID_1),
	BT_GATT_CHARACTERISTIC(UUID_2, BT_GATT_CHRC_READ, BT_GATT_PERM_READ,
			       read_mtu_validation_chrc, NULL, NULL),
};

static struct bt_gatt_service svc = {
	.attrs = attrs,
	.attr_count = ARRAY_SIZE(attrs),
};

static void find_the_chrc(struct bt_conn *conn, uint16_t *chrc_value_handle)
{
	uint16_t svc_handle;
	uint16_t svc_end_handle;
	uint16_t chrc_end_handle;

	EXPECT_ZERO(bt_testlib_gatt_discover_primary(&svc_handle, &svc_end_handle, conn, UUID_1, 1,
						     0xffff));

	LOG_INF("svc_handle: %u, svc_end_handle: %u", svc_handle, svc_end_handle);

	EXPECT_ZERO(bt_testlib_gatt_discover_characteristic(chrc_value_handle, &chrc_end_handle,
							    NULL, conn, UUID_2, (svc_handle + 1),
							    svc_end_handle));

	LOG_INF("chrc_value_handle: %u, chrc_end_handle: %u", *chrc_value_handle, chrc_end_handle);
}

static void bs_sync_all_log(char *log_msg)
{
	/* Everyone meets here. */
	bt_testlib_bs_sync_all();

	if (get_device_nbr() == 0) {
		LOG_WRN("Sync point: %s", log_msg);
	}

	/* Everyone waits for d0 to finish logging. */
	bt_testlib_bs_sync_all();
}

static inline void bt_enable_quiet(void)
{
	bt_testlib_log_level_set("bt_hci_core", LOG_LEVEL_ERR);
	bt_testlib_log_level_set("bt_id", LOG_LEVEL_ERR);

	EXPECT_ZERO(bt_enable(NULL));

	bt_testlib_log_level_set("bt_hci_core", LOG_LEVEL_INF);
	bt_testlib_log_level_set("bt_id", LOG_LEVEL_INF);
}

static void test_long_read(enum bt_att_chan_opt bearer, uint16_t chrc_value_handle,
			   struct bt_conn *conn)
{
	bool central = (get_device_nbr() == CENTRAL_DEVICE_NBR);

	if (central) {
		size_t read_count;

		NET_BUF_SIMPLE_DEFINE(attr_value_buf, BT_ATT_MAX_ATTRIBUTE_LEN);

		/* Perform the whole long read operation. */
		EXPECT_ZERO(bt_testlib_gatt_long_read(&attr_value_buf, NULL, NULL, conn, bearer,
						      chrc_value_handle, 0));

		/* Parse the read attribute value to verify the
		 * integrity of the transfer.
		 *
		 * Each response starts with the length of the whole
		 * response and the rest is zero-padded.
		 */
		for (read_count = 0; attr_value_buf.len; read_count++) {
			uint16_t encoded_len;
			uint16_t padding_size;

			LOG_INF("Verifying read %u", read_count);

			__ASSERT(attr_value_buf.len >= sizeof(encoded_len),
				 "Incomplete encoded length");
			encoded_len = net_buf_simple_pull_le16(&attr_value_buf);

			padding_size = (encoded_len - sizeof(uint16_t));
			LOG_INF("Padding size %u", padding_size);

			/* Check and discard padding. */
			for (uint16_t i = 0; i < padding_size; i++) {
				__ASSERT(attr_value_buf.len, "Unexpected end of buffer");
				__ASSERT(net_buf_simple_pull_u8(&attr_value_buf) == 0,
					 "Expected a padding byte at %u", i);
			}
		}
		LOG_INF("Verified %u reads", read_count);
		__ASSERT(read_count > 1, "Expected at least two reads");
	}
}

void the_test(void)
{
	bool central = (get_device_nbr() == CENTRAL_DEVICE_NBR);
	bool peripheral = (get_device_nbr() == PERIPHERAL_DEVICE_NBR);
	bt_addr_le_t adva;
	struct bt_conn *conn = NULL;
	uint16_t chrc_value_handle = 0;

	if (peripheral) {
		EXPECT_ZERO(bt_gatt_service_register(&svc));
	}

	bt_enable_quiet();

	if (peripheral) {
		EXPECT_ZERO(bt_set_name("peripheral"));
		EXPECT_ZERO(bt_testlib_adv_conn(
			&conn, BT_ID_DEFAULT,
			(BT_LE_ADV_OPT_USE_NAME | BT_LE_ADV_OPT_FORCE_NAME_IN_AD)));
	}

	if (central) {
		EXPECT_ZERO(bt_testlib_scan_find_name(&adva, "peripheral"));
		EXPECT_ZERO(bt_testlib_connect(&adva, &conn));

		/* Establish EATT bearers. */
		EXPECT_ZERO(bt_testlib_secure(conn, BT_SECURITY_L2));

		while (bt_eatt_count(conn) == 0) {
			k_msleep(100);
		};
	}

	bs_sync_all_log("Connected");

	/* Perform discovery. */
	if (central) {
		find_the_chrc(conn, &chrc_value_handle);
	}

	bs_sync_all_log("Testing UATT");
	test_long_read(BT_ATT_CHAN_OPT_UNENHANCED_ONLY, chrc_value_handle, conn);

	bs_sync_all_log("Testing EATT");
	test_long_read(BT_ATT_CHAN_OPT_ENHANCED_ONLY, chrc_value_handle, conn);

	bs_sync_all_log("Test Complete");

	PASS("Test complete\n");
}
