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

#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/services/ias.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/kernel.h>
#include <zephyr/settings/settings.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/check.h>
#include <zephyr/sys/printk.h>
#include <zephyr/types.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(peripheral, LOG_LEVEL_INF);

#include "bstests.h"
#include "bs_types.h"
#include "bs_tracing.h"
#include "bstests.h"
#include "bs_pc_backchannel.h"
#include "argparse.h"

#define TEST_ROUNDS 10
#define MIN_NOTIFICATIONS 50

#define NOTIFICATION_DATA_PREFIX     "Counter:"
#define NOTIFICATION_DATA_PREFIX_LEN (sizeof(NOTIFICATION_DATA_PREFIX) - 1)

#define CHARACTERISTIC_DATA_MAX_LEN 260
#define NOTIFICATION_DATA_LEN	    MAX(200, (CONFIG_BT_L2CAP_TX_MTU - 4))
BUILD_ASSERT(NOTIFICATION_DATA_LEN <= CHARACTERISTIC_DATA_MAX_LEN);

#define CENTRAL_SERVICE_UUID_VAL                                                                   \
	BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x5678, 0x1234, 0x56789abcdea0)

#define CENTRAL_CHARACTERISTIC_UUID_VAL                                                            \
	BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x5678, 0x1234, 0x56789abcdea1)

#define CENTRAL_SERVICE_UUID	    BT_UUID_DECLARE_128(CENTRAL_SERVICE_UUID_VAL)
#define CENTRAL_CHARACTERISTIC_UUID BT_UUID_DECLARE_128(CENTRAL_CHARACTERISTIC_UUID_VAL)

/* Custom Service Variables */
static struct bt_uuid_128 vnd_uuid =
	BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x5678, 0x1234, 0x56789abcdef0));

static struct bt_uuid_128 vnd_enc_uuid =
	BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x5678, 0x1234, 0x56789abcdef1));

enum {
	CONN_INFO_CONNECTED,
	CONN_INFO_SECURITY_LEVEL_UPDATED,
	CONN_INFO_MTU_EXCHANGED,
	CONN_INFO_DISCOVERING,
	CONN_INFO_SUBSCRIBED,
	/* Total number of flags - must be at the end of the enum */
	CONN_INFO_NUM_FLAGS,
};

struct active_conn_info {
	ATOMIC_DEFINE(flags, CONN_INFO_NUM_FLAGS);
	struct bt_conn *conn_ref;
	atomic_t notify_counter;
	atomic_t tx_notify_counter;
#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)
	struct bt_conn_le_data_len_param le_data_len_param;
#endif
};

static struct active_conn_info conn_info;

static uint32_t rounds;

/* This is outside the conn context since it can remain valid across
 * connections
 */
static uint8_t central_subscription;
static uint8_t tx_data[CHARACTERISTIC_DATA_MAX_LEN];
static uint32_t notification_size; /* TODO: does this _need_ to be set in args? */

static struct bt_uuid_128 uuid = BT_UUID_INIT_128(0);
static struct bt_gatt_discover_params discover_params;
static struct bt_gatt_subscribe_params subscribe_params;

static const struct bt_uuid_16 ccc_uuid = BT_UUID_INIT_16(BT_UUID_GATT_CCC_VAL);

static void vnd_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
	central_subscription = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0;
}

/* Vendor Primary Service Declaration */
BT_GATT_SERVICE_DEFINE(
	vnd_svc, BT_GATT_PRIMARY_SERVICE(&vnd_uuid),
	BT_GATT_CHARACTERISTIC(&vnd_enc_uuid.uuid,
			       BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | BT_GATT_CHRC_NOTIFY,
			       BT_GATT_PERM_READ | BT_GATT_PERM_WRITE, NULL, NULL,
			       NULL),
	BT_GATT_CCC(vnd_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
);

void mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
{
	LOG_INF("Updated MTU: TX: %d RX: %d bytes", tx, rx);

	if (tx == CONFIG_BT_L2CAP_TX_MTU && rx == CONFIG_BT_L2CAP_TX_MTU) {
		char addr[BT_ADDR_LE_STR_LEN];

		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

		atomic_set_bit(conn_info.flags, CONN_INFO_MTU_EXCHANGED);
		LOG_INF("Updating MTU succeeded %s", addr);
	}
}

static struct bt_gatt_cb gatt_callbacks = {.att_mtu_updated = mtu_updated};

static void connected(struct bt_conn *conn, uint8_t err)
{
	char addr[BT_ADDR_LE_STR_LEN];

	if (err) {
		memset(&conn_info, 0x00, sizeof(struct active_conn_info));
		LOG_ERR("Connection failed (err 0x%02x)", err);
		return;
	}

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	rounds++;
	conn_info.conn_ref = conn;

	atomic_set(&conn_info.tx_notify_counter, 0);
	atomic_set(&conn_info.notify_counter, 0);
	atomic_set_bit(conn_info.flags, CONN_INFO_CONNECTED);

	LOG_INF("Connection %p established : %s", conn, addr);
}

static void disconnected(struct bt_conn *conn, uint8_t reason)
{
	LOG_DBG("Disconnected (reason 0x%02x)", reason);

	/* With a lot of devices, it is possible that the central doesn't see
	 * the disconnect packet.
	 */
	bool valid_reason =
		reason == BT_HCI_ERR_LOCALHOST_TERM_CONN ||
		reason == BT_HCI_ERR_CONN_TIMEOUT;

	__ASSERT(valid_reason, "Disconnected (reason 0x%02x)", reason);

	memset(&conn_info, 0x00, sizeof(struct active_conn_info));

	if (rounds >= TEST_ROUNDS) {
		LOG_INF("Number of conn/disconn cycles reached, stopping advertiser...");
		bt_le_adv_stop();

		LOG_INF("Test passed");

		extern enum bst_result_t bst_result;

		bst_result = Passed;
	}
}

static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	LOG_DBG("LE conn param req: %s int (0x%04x (~%u ms), 0x%04x (~%u ms)) lat %d to %d",
		addr, param->interval_min, (uint32_t)(param->interval_min * 1.25),
		param->interval_max, (uint32_t)(param->interval_max * 1.25), param->latency,
		param->timeout);

	return true;
}

#if defined(CONFIG_BT_SMP)
static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if (err) {
		LOG_ERR("Security for %p failed: %s level %u err %d", conn, addr, level, err);
		return;
	}

	LOG_INF("Security for %p changed: %s level %u", conn, addr, level);
	atomic_set_bit(conn_info.flags, CONN_INFO_SECURITY_LEVEL_UPDATED);
}
#endif /* CONFIG_BT_SMP */

BT_CONN_CB_DEFINE(conn_callbacks) = {
	.connected = connected,
	.disconnected = disconnected,
	.le_param_req = le_param_req,
#if defined(CONFIG_BT_SMP)
	.security_changed = security_changed,
#endif /* CONFIG_BT_SMP */
};

static uint8_t rx_notification(struct bt_conn *conn, struct bt_gatt_subscribe_params *params,
			       const void *data, uint16_t length)
{
	const char *data_ptr = (const char *)data + NOTIFICATION_DATA_PREFIX_LEN;
	uint32_t received_counter;
	char addr[BT_ADDR_LE_STR_LEN];

	if (!data) {
		LOG_INF("[UNSUBSCRIBED]");
		params->value_handle = 0U;
		return BT_GATT_ITER_STOP;
	}

	/* TODO: enable */
	/* __ASSERT_NO_MSG(atomic_test_bit(conn_info.flags, CONN_INFO_SUBSCRIBED)); */

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	received_counter = strtoul(data_ptr, NULL, 0);
	LOG_INF("RX %d", received_counter);

	__ASSERT(atomic_get(&conn_info.notify_counter) == received_counter,
		 "expected counter : %u , received counter : %u",
		 atomic_get(&conn_info.notify_counter), received_counter);

	atomic_inc(&conn_info.notify_counter);

	return BT_GATT_ITER_CONTINUE;
}

static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *attr,
			     struct bt_gatt_discover_params *params)
{
	int err;
	char uuid_str[BT_UUID_STR_LEN];

	if (!attr) {
		LOG_INF("Discover complete");
		(void)memset(params, 0, sizeof(*params));
		return BT_GATT_ITER_STOP;
	}

	bt_uuid_to_str(params->uuid, uuid_str, sizeof(uuid_str));
	LOG_DBG("UUID found : %s", uuid_str);

	LOG_DBG("[ATTRIBUTE] handle %u", attr->handle);

	if (discover_params.type == BT_GATT_DISCOVER_PRIMARY) {
		LOG_DBG("Primary Service Found");
		memcpy(&uuid, CENTRAL_CHARACTERISTIC_UUID, sizeof(uuid));
		discover_params.uuid = &uuid.uuid;
		discover_params.start_handle = attr->handle + 1;
		discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;

		err = bt_gatt_discover(conn, &discover_params);
		if (err == -ENOMEM) {
			goto nomem;
		}

		__ASSERT(!err, "Discover failed (err %d)", err);

	} else if (discover_params.type == BT_GATT_DISCOVER_CHARACTERISTIC) {
		LOG_DBG("Service Characteristic Found");

		params->uuid = &ccc_uuid.uuid;
		params->start_handle = attr->handle + 2;
		params->type = BT_GATT_DISCOVER_DESCRIPTOR;
		subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);

		err = bt_gatt_discover(conn, params);
		if (err == -ENOMEM) {
			goto nomem;
		}

		__ASSERT(!err, "Discover failed (err %d)", err);

	} else if (atomic_test_and_clear_bit(conn_info.flags, CONN_INFO_DISCOVERING)) {

		subscribe_params.notify = rx_notification;
		subscribe_params.value = BT_GATT_CCC_NOTIFY;
		subscribe_params.ccc_handle = attr->handle;

		LOG_ERR("subscribe");
		err = bt_gatt_subscribe(conn, &subscribe_params);
		if (err == -ENOMEM) {
			goto nomem;
		}

		if (err != -EALREADY) {
			__ASSERT(!err, "Subscribe failed (err %d)", err);
		}

		__ASSERT_NO_MSG(!atomic_test_bit(conn_info.flags, CONN_INFO_SUBSCRIBED));
		atomic_set_bit(conn_info.flags, CONN_INFO_SUBSCRIBED);

		char addr[BT_ADDR_LE_STR_LEN];

		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
		LOG_INF("[SUBSCRIBED] addr %s", addr);
	}

	return BT_GATT_ITER_STOP;

nomem:
	/* if we're out of buffers or metadata contexts, restart discovery
	 * later.
	 */
	LOG_ERR("out of memory, retry sub later");
	atomic_clear_bit(conn_info.flags, CONN_INFO_DISCOVERING);

	return BT_GATT_ITER_STOP;
}

static void subscribe_to_service(struct bt_conn *conn)
{
	while (!atomic_test_and_set_bit(conn_info.flags, CONN_INFO_DISCOVERING) &&
	       !atomic_test_bit(conn_info.flags, CONN_INFO_SUBSCRIBED)) {
		int err;
		char addr[BT_ADDR_LE_STR_LEN];

		bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

		memcpy(&uuid, CENTRAL_SERVICE_UUID, sizeof(uuid));
		discover_params.uuid = &uuid.uuid;
		discover_params.func = discover_func;
		discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
		discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
		discover_params.type = BT_GATT_DISCOVER_PRIMARY;

		err = bt_gatt_discover(conn, &discover_params);
		if (err == -ENOMEM) {
			LOG_DBG("out of memory, retry sub later");
			atomic_clear_bit(conn_info.flags, CONN_INFO_DISCOVERING);
		}

		__ASSERT(!err, "Subscribe failed (err %d)", err);

		while (atomic_test_bit(conn_info.flags, CONN_INFO_DISCOVERING) &&
		       !atomic_test_bit(conn_info.flags, CONN_INFO_SUBSCRIBED)) {
			k_sleep(K_MSEC(10));
		}
	}
}

void set_tx_payload(uint32_t count)
{
	memset(tx_data, 0x00, sizeof(tx_data));
	snprintk(tx_data, notification_size, "%s%u", NOTIFICATION_DATA_PREFIX, count);
}

void disconnect(void)
{
	/* we should always be the ones doing the disconnecting */
	__ASSERT_NO_MSG(conn_info.conn_ref);

	int err = bt_conn_disconnect(conn_info.conn_ref,
				     BT_HCI_ERR_REMOTE_POWER_OFF);

	if (err) {
		LOG_ERR("Terminating conn failed (err %d)", err);
	}

	/* wait for disconnection callback */
	while (atomic_test_bit(conn_info.flags, CONN_INFO_CONNECTED)) {
		k_sleep(K_MSEC(10));
	}
}

void test_peripheral_main(void)
{
	struct bt_gatt_attr *vnd_attr;
	char name[10];
	int err;

	err = bt_enable(NULL);
	if (err) {
		LOG_ERR("Bluetooth init failed (err %d)", err);
		return;
	}
	LOG_DBG("Bluetooth initialized");

	sprintf(name, "per-%d", get_device_nbr());
	bt_set_name(name);

	err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, NULL, 0, NULL, 0);
	if (err) {
		LOG_ERR("Advertising failed to start (err %d)", err);
		__ASSERT_NO_MSG(err);
	}
	LOG_INF("Started advertising");

	bt_gatt_cb_register(&gatt_callbacks);

	vnd_attr = bt_gatt_find_by_uuid(vnd_svc.attrs, vnd_svc.attr_count, &vnd_enc_uuid.uuid);

	while (true) {
		LOG_DBG("Waiting for connection from central..");
		while (!atomic_test_bit(conn_info.flags, CONN_INFO_CONNECTED)) {
			k_sleep(K_MSEC(10));
		}

		LOG_DBG("Subscribing to central..");
		subscribe_to_service(conn_info.conn_ref);

		LOG_DBG("Waiting until central subscribes..");
		while (!central_subscription) {
			k_sleep(K_MSEC(10));
		}

		while (!atomic_test_bit(conn_info.flags, CONN_INFO_MTU_EXCHANGED)) {
			k_sleep(K_MSEC(10));
		}

		LOG_INF("Begin sending notifications to central..");
		while (central_subscription &&
		       atomic_test_bit(conn_info.flags, CONN_INFO_CONNECTED)) {

			set_tx_payload(atomic_get(&conn_info.tx_notify_counter));
			err = bt_gatt_notify(NULL, vnd_attr, tx_data, notification_size);
			if (err) {
				if (atomic_get(&conn_info.tx_notify_counter) > 0) {
					atomic_dec(&conn_info.tx_notify_counter);
				}
				LOG_DBG("Couldn't send GATT notification");
				k_msleep(10);
			} else {
				atomic_inc(&conn_info.tx_notify_counter);
				LOG_INF("TX %d", atomic_get(&conn_info.tx_notify_counter));
			}

			if (atomic_get(&conn_info.tx_notify_counter) > MIN_NOTIFICATIONS &&
			    atomic_get(&conn_info.notify_counter) > MIN_NOTIFICATIONS) {
				LOG_INF("Disconnecting..");
				disconnect();
			}
		}
	}
}

void test_init(void)
{
	extern enum bst_result_t bst_result;

	LOG_INF("Initializing Test");
	bst_result = Failed;
}

static void test_args(int argc, char **argv)
{
	notification_size = NOTIFICATION_DATA_LEN;

	if (argc >= 1) {
		char const *ptr;

		ptr = strstr(argv[0], "notify_size=");
		if (ptr != NULL) {
			ptr += strlen("notify_size=");
			notification_size = atol(ptr);
			notification_size = MIN(NOTIFICATION_DATA_LEN, notification_size);
		}
	}

	bs_trace_raw(0, "Notification data size : %d\n", notification_size);
}

static const struct bst_test_instance test_def[] = {
	{
		.test_id = "peripheral",
		.test_descr = "Peripheral Connection Stress",
		.test_args_f = test_args,
		.test_post_init_f = test_init,
		.test_main_f = test_peripheral_main
	},
	BSTEST_END_MARKER
};

struct bst_test_list *test_main_conn_stress_install(struct bst_test_list *tests)
{
	return bst_add_tests(tests, test_def);
}

extern struct bst_test_list *test_main_conn_stress_install(struct bst_test_list *tests);

bst_test_install_t test_installers[] = {
	test_main_conn_stress_install,
	NULL
};

int main(void)
{
	bst_main();

	return 0;
}
