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

#include "bs_dynargs.h"
#include "bs_pc_backchannel.h"
#include <argparse.h>
#include <posix_native_task.h>

#include "common.h"

extern enum bst_result_t bst_result;
struct bt_conn *default_conn;
atomic_t flag_connected;
atomic_t flag_disconnected;
atomic_t flag_conn_updated;
volatile bt_security_t security_level;

const struct bt_data ad[AD_SIZE] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR))
};

static void device_found(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;
	}

	/* We're only interested in connectable events */
	if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) == 0) {
		return;
	}

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

	/* connect only to devices in close proximity */
	if (info->rssi < -70) {
		FAIL("RSSI too low");
		return;
	}

	printk("Stopping scan\n");
	if (bt_le_scan_stop()) {
		FAIL("Could not stop scan");
		return;
	}

	err = bt_conn_le_create(info->addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT,
				&default_conn);
	if (err) {
		FAIL("Could not connect to peer: %d", err);
	}
}

struct bt_le_scan_cb common_scan_cb = {
	.recv = device_found,
};

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

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

	if (default_conn == NULL) {
		default_conn = bt_conn_ref(conn);
	}

	if (err != 0) {
		bt_conn_unref(default_conn);
		default_conn = NULL;

		FAIL("Failed to connect to %s (0x%02x)\n", addr, err);
		return;
	}

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

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

	printk("Disconnected: %s (reason 0x%02x)\n", addr, reason);

	bt_conn_unref(default_conn);
	default_conn = NULL;
	UNSET_FLAG(flag_connected);
	UNSET_FLAG(flag_conn_updated);
	SET_FLAG(flag_disconnected);

	security_level = BT_SECURITY_L1;
}

static void conn_param_updated_cb(struct bt_conn *conn, uint16_t interval, uint16_t latency,
				  uint16_t timeout)
{
	printk("Connection parameter updated: %p 0x%04X (%u us), 0x%04X, 0x%04X\n", conn, interval,
	       BT_CONN_INTERVAL_TO_US(interval), latency, timeout);

	SET_FLAG(flag_conn_updated);
}

static void security_changed_cb(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
{
	printk("Security changed: %p level %d err %d\n", conn, level, err);

	if (err == BT_SECURITY_ERR_SUCCESS) {
		security_level = level;
	}
}

BT_CONN_CB_DEFINE(conn_callbacks) = {
	.connected = connected,
	.disconnected = disconnected,
	.le_param_updated = conn_param_updated_cb,
	.security_changed = security_changed_cb,
};

void test_tick(bs_time_t HW_device_time)
{
	if (bst_result != Passed) {
		FAIL("test failed (not passed after %i seconds)\n", WAIT_SECONDS);
	}
}

void test_init(void)
{
	bst_ticker_set_next_tick_absolute(WAIT_TIME);
	bst_result = In_progress;
}

#define SYNC_MSG_SIZE 1
static int32_t dev_cnt;
static uint backchannel_nums[255];
static uint chan_cnt;

static void register_more_cmd_args(void)
{
	static bs_args_struct_t args_struct_toadd[] = {
		{
			.option = "D",
			.name = "number_devices",
			.type = 'i',
			.dest = (void *)&dev_cnt,
			.descript = "Number of devices which will connect in this phy",
			.is_mandatory = true,
		},
		ARG_TABLE_ENDMARKER,
	};

	bs_add_extra_dynargs(args_struct_toadd);
}
NATIVE_TASK(register_more_cmd_args, PRE_BOOT_1, 100);

uint16_t get_dev_cnt(void)
{
	return (uint16_t)dev_cnt;
}

/**
 * @brief Get the channel id based on remote device ID
 *
 * The is effectively a very simple hashing function to generate unique channel IDs from device IDs
 *
 * @param dev 16-bit device ID
 *
 * @return uint 32-bit channel ID
 */
static uint get_chan_num(uint16_t dev)
{
	uint16_t self = (uint16_t)bsim_args_get_global_device_nbr();
	uint channel_id;

	if (self < dev) {
		channel_id = (dev << 16) | self;
	} else {
		channel_id = (self << 16) | dev;
	}

	return channel_id;
}

/**
 * @brief Set up the backchannels between each pair of device
 *
 * Each pair of devices will get a unique channel
 */
static void setup_backchannels(void)
{
	__ASSERT_NO_MSG(dev_cnt > 0 && dev_cnt < ARRAY_SIZE(backchannel_nums));
	const uint self = bsim_args_get_global_device_nbr();
	uint device_numbers[dev_cnt];
	uint *channels;

	for (int32_t i = 0; i < dev_cnt; i++) {
		if (i != self) { /* skip ourselves*/
			backchannel_nums[chan_cnt] = get_chan_num((uint16_t)i);
			device_numbers[chan_cnt++] = i;
		}
	}

	channels = bs_open_back_channel(self, device_numbers, backchannel_nums, chan_cnt);
	__ASSERT_NO_MSG(channels != NULL);
}
NATIVE_TASK(setup_backchannels, PRE_BOOT_3, 100);

static uint get_chan_id_from_chan_num(uint chan_num)
{
	for (uint i = 0; i < ARRAY_SIZE(backchannel_nums); i++) {
		if (backchannel_nums[i] == chan_num) {
			return i;
		}
	}

	return 0;
}

void backchannel_sync_send(uint dev)
{
	const uint chan_id = get_chan_id_from_chan_num(get_chan_num((uint16_t)dev));
	uint8_t sync_msg[SYNC_MSG_SIZE] = {0};

	printk("Sending sync to %u\n", chan_id);
	bs_bc_send_msg(chan_id, sync_msg, ARRAY_SIZE(sync_msg));
}

void backchannel_sync_send_all(void)
{
	for (int32_t i = 0; i < dev_cnt; i++) {
		const uint self = bsim_args_get_global_device_nbr();

		if (i != self) { /* skip ourselves*/
			backchannel_sync_send(i);
		}
	}
}

void backchannel_sync_wait(uint dev)
{
	const uint chan_id = get_chan_id_from_chan_num(get_chan_num((uint16_t)dev));

	printk("Waiting for sync to %u\n", chan_id);

	while (true) {
		if (bs_bc_is_msg_received(chan_id) > 0) {
			uint8_t sync_msg[SYNC_MSG_SIZE];

			bs_bc_receive_msg(chan_id, sync_msg, ARRAY_SIZE(sync_msg));
			/* We don't really care about the content of the message */
			break;
		}

		k_sleep(K_MSEC(1));
	}
}

void backchannel_sync_wait_all(void)
{
	for (int32_t i = 0; i < dev_cnt; i++) {
		const uint self = bsim_args_get_global_device_nbr();

		if (i != self) { /* skip ourselves*/
			backchannel_sync_wait(i);
		}
	}
}

void backchannel_sync_wait_any(void)
{
	while (true) {
		for (int32_t i = 0; i < dev_cnt; i++) {
			const uint self = bsim_args_get_global_device_nbr();

			if (i != self) { /* skip ourselves*/
				const uint chan_id =
					get_chan_id_from_chan_num(get_chan_num((uint16_t)i));

				if (bs_bc_is_msg_received(chan_id) > 0) {
					uint8_t sync_msg[SYNC_MSG_SIZE];

					bs_bc_receive_msg(chan_id, sync_msg, ARRAY_SIZE(sync_msg));
					/* We don't really care about the content of the message */

					return;
				}
			}
		}

		k_sleep(K_MSEC(100));
	}
}

void backchannel_sync_clear(uint dev)
{
	const uint chan_id = get_chan_id_from_chan_num(get_chan_num((uint16_t)dev));

	while (bs_bc_is_msg_received(chan_id)) {
		uint8_t sync_msg[SYNC_MSG_SIZE];

		bs_bc_receive_msg(chan_id, sync_msg, ARRAY_SIZE(sync_msg));
		/* We don't really care about the content of the message */
	}
}

void backchannel_sync_clear_all(void)
{
	for (int32_t i = 0; i < dev_cnt; i++) {
		const uint self = bsim_args_get_global_device_nbr();

		if (i != self) { /* skip ourselves*/
			backchannel_sync_clear(i);
		}
	}
}
