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

#include <stddef.h>
#include <stdint.h>
#include <string.h>

#include <zephyr/kernel.h>

#include <zephyr/sys/printk.h>

#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/bluetooth.h>

#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(bt_bsim_privacy, LOG_LEVEL_INF);

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

#define CREATE_FLAG(flag) static atomic_t flag = (atomic_t) false
#define SET_FLAG(flag)	  (void)atomic_set(&flag, (atomic_t) true)
#define GET_FLAG(flag)	  (bool)atomic_get(&flag)
#define UNSET_FLAG(flag)  (void)atomic_set(&flag, (atomic_t) false)
#define WAIT_FOR_FLAG(flag)                                                                        \
	while (!(bool)atomic_get(&flag)) {                                                         \
		(void)k_sleep(K_MSEC(1));                                                          \
	}

#define FAIL(...)                                                                                  \
	do {                                                                                       \
		bst_result = Failed;                                                               \
		bs_trace_error_time_line(__VA_ARGS__);                                             \
	} while (0)

#define PASS(...)                                                                                  \
	do {                                                                                       \
		bst_result = Passed;                                                               \
		bs_trace_info_time(1, __VA_ARGS__);                                                \
	} while (0)

extern enum bst_result_t bst_result;

CREATE_FLAG(paired);
CREATE_FLAG(rpa_tested);
CREATE_FLAG(identity_tested);

static void start_scan(void);

static struct bt_conn *default_conn;

static bt_addr_le_t peer_rpa;
static bt_addr_le_t peer_identity;

enum addr_type_t {
	RPA,
	IDENTITY_ADDR,
};
static enum addr_type_t test_addr_type;

static bool use_active_scan;
static bool connection_test;

static int sim_id;

void central_test_args_parse(int argc, char *argv[])
{
	char *addr_type_arg = NULL;

	bs_args_struct_t args_struct[] = {
		{
			.dest = &sim_id,
			.type = 'i',
			.name = "{positive integer}",
			.option = "sim-id",
			.descript = "Simulation ID counter",
		},
		{
			.dest = &addr_type_arg,
			.type = 's',
			.name = "{identity, rpa}",
			.option = "addr-type",
			.descript = "Address type to test",
		},
		{
			.dest = &use_active_scan,
			.type = 'b',
			.name = "{0, 1}",
			.option = "active-scan",
			.descript = "",
		},
		{
			.dest = &connection_test,
			.type = 'b',
			.name = "{0, 1}",
			.option = "connection-test",
			.descript = "",
		},
	};

	bs_args_parse_all_cmd_line(argc, argv, args_struct);

	if (addr_type_arg != NULL) {
		if (!strcmp(addr_type_arg, "identity")) {
			test_addr_type = IDENTITY_ADDR;
		} else if (!strcmp(addr_type_arg, "rpa")) {
			test_addr_type = RPA;
		}
	}
}

static void wait_check_result(void)
{
	if (test_addr_type == IDENTITY_ADDR) {
		WAIT_FOR_FLAG(identity_tested);
		LOG_INF("Identity address tested");
	} else if (test_addr_type == RPA) {
		WAIT_FOR_FLAG(rpa_tested);
		LOG_INF("Resolvable Private Address tested");
	}
}

static void check_addresses(const bt_addr_le_t *peer_addr)
{
	LOG_DBG("Check addresses");

	bool addr_equal;

	if (test_addr_type == IDENTITY_ADDR) {
		SET_FLAG(identity_tested);
		addr_equal = bt_addr_le_eq(&peer_identity, peer_addr);
		if (!addr_equal) {
			FAIL("The peer address is not the same as the peer previously paired.\n");
		}
	} else if (test_addr_type == RPA) {
		SET_FLAG(rpa_tested);
		addr_equal = bt_addr_le_eq(&peer_identity, peer_addr);
		if (!addr_equal) {
			FAIL("The resolved address is not the same as the peer previously "
			     "paired.\n");
		}
	}
}



static void scan_recv(const struct bt_le_scan_recv_info *info,
		      struct net_buf_simple *ad)
{
	char addr_str[BT_ADDR_LE_STR_LEN];
	int err;

	if (default_conn) {
		return;
	}

	bt_addr_le_to_str(info->addr, addr_str, sizeof(addr_str));
	LOG_INF("Device found: %s (RSSI %d)", addr_str, info->rssi);

	/* In the case of extended advertising and active scanning, this
	 * callback will be called twice: once for the AUX_ADV_IND and
	 * another time for the AUX_SCAN_RSP.
	 *
	 * We have to be careful not to stop the scanner before we have gotten
	 * the second one, as the peripheral side waits until it gets an
	 * AUX_SCAN_REQ to end the test.
	 *
	 * There is a catch though, since we have to bond, in order to exchange
	 * the address resolving keys, then this check should only apply after
	 * the pairing is done.
	 */
	if (GET_FLAG(paired) &&
	    info->adv_props == (BT_GAP_ADV_PROP_EXT_ADV | BT_GAP_ADV_PROP_SCANNABLE)) {
		LOG_DBG("skipping AUX_ADV_IND report, waiting for AUX_SCAN_REQ "
			"(props: 0x%x)", info->adv_props);
		return;
	}

	if (GET_FLAG(paired)) {
		check_addresses(info->addr);
	}

	if (connection_test || !GET_FLAG(paired)) {
		if (bt_le_scan_stop()) {
			LOG_DBG("Failed to stop scanner");
			return;
		}
		LOG_DBG("Scanner stopped: conn %d paired %d", connection_test, GET_FLAG(paired));

		err = bt_conn_le_create(info->addr,
					BT_CONN_LE_CREATE_CONN,
					BT_LE_CONN_PARAM_DEFAULT,
					&default_conn);
		if (err) {
			LOG_DBG("Create conn to %s failed (%u)", addr_str, err);
			start_scan();
		}
	}
}

static struct bt_le_scan_cb scan_cb = {
	.recv = scan_recv,
};

static void start_scan(void)
{
	int err;

	LOG_DBG("Using %s scan", use_active_scan ? "active" : "passive");

	err = bt_le_scan_start(use_active_scan ? BT_LE_SCAN_ACTIVE : BT_LE_SCAN_PASSIVE,
			       NULL);

	if (err) {
		FAIL("Scanning failed to start (err %d)\n", err);
	}

	LOG_DBG("Scanning successfully started");
}

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));

	LOG_DBG("Connected: %s", addr);
}

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

	if (conn != default_conn) {
		return;
	}

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

	LOG_DBG("Disconnected: %s (reason 0x%02x)", addr, reason);

	bt_conn_unref(default_conn);
	default_conn = NULL;

	start_scan();
}

static void identity_resolved(struct bt_conn *conn, const bt_addr_le_t *rpa,
			      const bt_addr_le_t *identity)
{
	char addr_identity[BT_ADDR_LE_STR_LEN];
	char addr_rpa[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(identity, addr_identity, sizeof(addr_identity));
	bt_addr_le_to_str(rpa, addr_rpa, sizeof(addr_rpa));

	LOG_DBG("Identity resolved %s -> %s", addr_rpa, addr_identity);

	bt_addr_le_copy(&peer_rpa, rpa);
	bt_addr_le_copy(&peer_identity, identity);

	SET_FLAG(paired);
}

static struct bt_conn_cb central_cb;

void test_central(void)
{
	int err;

	LOG_DBG("Central device");

	central_cb.connected = connected;
	central_cb.disconnected = disconnected;
	central_cb.identity_resolved = identity_resolved;

	bt_conn_cb_register(&central_cb);
	bt_le_scan_cb_register(&scan_cb);

	err = bt_enable(NULL);
	if (err) {
		FAIL("Bluetooth init failed (err %d)\n", err);
	}

	UNSET_FLAG(identity_tested);
	UNSET_FLAG(rpa_tested);

	start_scan();

	wait_check_result();
}

void test_central_main(void)
{
	char *addr_tested = "";

	if (test_addr_type == RPA) {
		addr_tested = "RPA";
	} else if (test_addr_type == IDENTITY_ADDR) {
		addr_tested = "identity address";
	}

	LOG_INF("Central test START (id: %d: params: %s scan, %sconnectable test, testing %s)\n",
		sim_id, use_active_scan ? "active" : "passive", connection_test ? "" : "non-",
		addr_tested);

	test_central();

	PASS("passed\n");
}
