/*
 * Copyright (c) 2023 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <zephyr/kernel.h>

#include "bs_types.h"
#include "bs_tracing.h"
#include "time_machine.h"
#include "bstests.h"

#include <zephyr/types.h>
#include <zephyr/sys/printk.h>

#include <zephyr/bluetooth/bluetooth.h>

#include "common.h"

extern enum bst_result_t bst_result;

static struct bt_conn *g_conn;

CREATE_FLAG(flag_connected);
CREATE_FLAG(flag_bonded);

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

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

	if (err != BT_HCI_ERR_SUCCESS) {
		FAIL("Failed to connect to %s: %u\n", addr, err);
		return;
	}

	printk("Connected to %s\n", addr);
	g_conn = bt_conn_ref(conn);
	SET_FLAG(flag_connected);
}

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

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

	printk("Disconnected: %s (reason %u)\n", addr, reason);

	bt_conn_unref(g_conn);
	g_conn = NULL;
}

static struct bt_conn_cb conn_cbs = {
	.connected = connected,
	.disconnected = disconnected,
};

static void pairing_complete_cb(struct bt_conn *conn, bool bonded)
{
	if (conn == g_conn && bonded) {
		SET_FLAG(flag_bonded);
	}
}

static struct bt_conn_auth_info_cb auto_info_cbs = {
	.pairing_complete = pairing_complete_cb,
};

static void common_init(void)
{
	int err;

	err = bt_enable(NULL);

	if (err) {
		FAIL("Bluetooth init failed: %d\n", err);
		return;
	}
	printk("Bluetooth initialized\n");

	bt_conn_cb_register(&conn_cbs);
	bt_conn_auth_info_cb_register(&auto_info_cbs);
}

static void create_per_adv_set(struct bt_le_ext_adv **adv)
{
	int err;

	printk("Creating extended advertising set...");
	err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv);
	if (err) {
		printk("Failed to create advertising set: %d\n", err);
		return;
	}
	printk("done.\n");

	printk("Setting periodic advertising parameters...");
	err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_DEFAULT);
	if (err) {
		printk("Failed to set periodic advertising parameters: %d\n",
		       err);
		return;
	}
	printk("done.\n");
}

static void create_conn_adv_set(struct bt_le_ext_adv **adv)
{
	int err;

	printk("Creating connectable extended advertising set...");
	err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, adv);
	if (err) {
		printk("Failed to create advertising set: %d\n", err);
		return;
	}
	printk("done.\n");
}

static void start_ext_adv_set(struct bt_le_ext_adv *adv)
{
	int err;

	printk("Starting Extended Advertising...");
	err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
	if (err) {
		printk("Failed to start extended advertising: %d\n", err);
		return;
	}
	printk("done.\n");
}

static void start_per_adv_set(struct bt_le_ext_adv *adv)
{
	int err;

	printk("Starting periodic advertising...");
	err = bt_le_per_adv_start(adv);
	if (err) {
		printk("Failed to start periodic advertising: %d\n", err);
		return;
	}
	printk("done.\n");
}

#if defined(CONFIG_BT_PER_ADV)
static void set_per_adv_data(struct bt_le_ext_adv *adv)
{
	int err;
	const struct bt_data ad[] = {
		BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, ARRAY_SIZE(mfg_data)),
		BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, ARRAY_SIZE(mfg_data))};

	printk("Setting Periodic Advertising Data...");
	err = bt_le_per_adv_set_data(adv, ad, ARRAY_SIZE(ad));
	if (err) {
		printk("Failed to set periodic advertising data: %d\n",
		       err);
		return;
	}
	printk("done.\n");
}
#endif

static void stop_ext_adv_set(struct bt_le_ext_adv *adv)
{
	int err;

	printk("Stopping Extended Advertising...");
	err = bt_le_ext_adv_stop(adv);
	if (err) {
		printk("Failed to stop extended advertising: %d\n",
		       err);
		return;
	}
	printk("done.\n");
}

static void stop_per_adv_set(struct bt_le_ext_adv *adv)
{
	int err;

	printk("Stopping Periodic Advertising...");
	err = bt_le_per_adv_stop(adv);
	if (err) {
		printk("Failed to stop periodic advertising: %d\n",
		       err);
		return;
	}
	printk("done.\n");
}

static void delete_adv_set(struct bt_le_ext_adv *adv)
{
	int err;

	printk("Delete extended advertising set...");
	err = bt_le_ext_adv_delete(adv);
	if (err) {
		printk("Failed Delete extended advertising set: %d\n", err);
		return;
	}
	printk("done.\n");
}

static void main_per_adv_advertiser(void)
{
	struct bt_le_ext_adv *per_adv;

	common_init();

	create_per_adv_set(&per_adv);

	start_per_adv_set(per_adv);
	start_ext_adv_set(per_adv);

	/* Advertise for a bit */
	k_sleep(K_SECONDS(10));

	stop_per_adv_set(per_adv);
	stop_ext_adv_set(per_adv);

	delete_adv_set(per_adv);
	per_adv = NULL;

	PASS("Periodic advertiser passed\n");
}

static void main_per_adv_conn_advertiser(void)
{
	struct bt_le_ext_adv *conn_adv;
	struct bt_le_ext_adv *per_adv;

	common_init();

	create_per_adv_set(&per_adv);
	create_conn_adv_set(&conn_adv);

	start_per_adv_set(per_adv);
	start_ext_adv_set(per_adv);
	start_ext_adv_set(conn_adv);

	WAIT_FOR_FLAG(flag_connected);

	/* Advertise for a bit */
	k_sleep(K_SECONDS(10));

	stop_per_adv_set(per_adv);
	stop_ext_adv_set(per_adv);
	stop_ext_adv_set(conn_adv);

	delete_adv_set(per_adv);
	per_adv = NULL;
	delete_adv_set(conn_adv);
	conn_adv = NULL;

	PASS("Periodic advertiser passed\n");
}

static void main_per_adv_conn_privacy_advertiser(void)
{
	struct bt_le_ext_adv *conn_adv;
	struct bt_le_ext_adv *per_adv;

	common_init();

	create_conn_adv_set(&conn_adv);

	start_ext_adv_set(conn_adv);

	WAIT_FOR_FLAG(flag_connected);
	WAIT_FOR_FLAG(flag_bonded);

	/* Start periodic advertising after bonding so that the scanner gets
	 * the resolved address
	 */
	create_per_adv_set(&per_adv);
	start_per_adv_set(per_adv);
	start_ext_adv_set(per_adv);

	/* Advertise for a bit */
	k_sleep(K_SECONDS(10));

	stop_per_adv_set(per_adv);
	stop_ext_adv_set(per_adv);
	stop_ext_adv_set(conn_adv);

	delete_adv_set(per_adv);
	per_adv = NULL;
	delete_adv_set(conn_adv);
	conn_adv = NULL;

	PASS("Periodic advertiser passed\n");
}

static void main_per_adv_long_data_advertiser(void)
{
#if defined(CONFIG_BT_PER_ADV)
	struct bt_le_ext_adv *per_adv;

	common_init();

	create_per_adv_set(&per_adv);

	set_per_adv_data(per_adv);
	start_per_adv_set(per_adv);
	start_ext_adv_set(per_adv);

	/* Advertise for a bit */
	k_sleep(K_SECONDS(10));

	stop_per_adv_set(per_adv);
	stop_ext_adv_set(per_adv);

	delete_adv_set(per_adv);
	per_adv = NULL;
#endif
	PASS("Periodic long data advertiser passed\n");
}

static const struct bst_test_instance per_adv_advertiser[] = {
	{
		.test_id = "per_adv_advertiser",
		.test_descr = "Basic periodic advertising test. "
			      "Will just start periodic advertising.",
		.test_post_init_f = test_init,
		.test_tick_f = test_tick,
		.test_main_f = main_per_adv_advertiser
	},
	{
		.test_id = "per_adv_conn_advertiser",
		.test_descr = "Periodic advertising test with concurrent ACL "
			      "and PA sync.",
		.test_post_init_f = test_init,
		.test_tick_f = test_tick,
		.test_main_f = main_per_adv_conn_advertiser
	},
	{
		.test_id = "per_adv_conn_privacy_advertiser",
		.test_descr = "Periodic advertising test with concurrent ACL "
			      "with bonding and PA sync.",
		.test_post_init_f = test_init,
		.test_tick_f = test_tick,
		.test_main_f = main_per_adv_conn_privacy_advertiser
	},
	{
		.test_id = "per_adv_long_data_advertiser",
		.test_descr = "Periodic advertising test with a longer data length. "
			      "To test the syncers reassembly of large data packets",
		.test_post_init_f = test_init,
		.test_tick_f = test_tick,
		.test_main_f = main_per_adv_long_data_advertiser
	},
	BSTEST_END_MARKER
};

struct bst_test_list *test_per_adv_advertiser(struct bst_test_list *tests)
{
	return bst_add_tests(tests, per_adv_advertiser);
}
