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

#include "common.h"

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

extern enum bst_result_t bst_result;

static struct bt_conn *default_conn;

#define PSM 0x80

CREATE_FLAG(is_connected);
CREATE_FLAG(chan_connected);
CREATE_FLAG(data_received);

#define DATA_BYTE_VAL  0xBB

/* L2CAP channel buffer pool */
NET_BUF_POOL_DEFINE(buf_pool, 1, BT_L2CAP_SDU_BUF_SIZE(16), CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);

static void chan_connected_cb(struct bt_l2cap_chan *l2cap_chan)
{
	struct net_buf *buf;
	int err;

	/* Send data immediately on L2CAP connection */
	buf = net_buf_alloc(&buf_pool, K_NO_WAIT);
	if (!buf) {
		FAIL("Buffer allocation failed\n");
	}

	(void)net_buf_reserve(buf, BT_L2CAP_SDU_CHAN_SEND_RESERVE);
	(void)net_buf_add_u8(buf, DATA_BYTE_VAL);

	/* Try to send data */
	err = bt_l2cap_chan_send(l2cap_chan, buf);
	if (err < 0) {
		FAIL("Could not send data, error %d\n", err);
	}

	SET_FLAG(chan_connected);
}

static void chan_disconnected_cb(struct bt_l2cap_chan *l2cap_chan)
{
	(void)l2cap_chan;

	UNSET_FLAG(chan_connected);
}

static int chan_recv_cb(struct bt_l2cap_chan *chan, struct net_buf *buf)
{
	(void)chan;

	if ((buf->len != 1) || (buf->data[0] != DATA_BYTE_VAL)) {
		FAIL("Unexpected data received");
	}

	SET_FLAG(data_received);

	return 0;
}

static const struct bt_l2cap_chan_ops l2cap_ops = {
	.connected = chan_connected_cb,
	.disconnected = chan_disconnected_cb,
	.recv = chan_recv_cb,
};

static struct bt_l2cap_le_chan channel;

static int accept(struct bt_conn *conn, struct bt_l2cap_server *server,
		  struct bt_l2cap_chan **l2cap_chan)
{
	channel.chan.ops = &l2cap_ops;
	*l2cap_chan = &channel.chan;

	return 0;
}

static struct bt_l2cap_server server = {
	.accept = accept,
	.sec_level = BT_SECURITY_L1,
	.psm = PSM,
};

static void connect_l2cap_channel(void)
{
	struct bt_l2cap_chan *chans[] = {&channel.chan, NULL};
	int err;

	channel.chan.ops = &l2cap_ops;

	if (IS_ENABLED(CONFIG_BT_L2CAP_ECRED)) {
		err = bt_l2cap_ecred_chan_connect(default_conn, chans, server.psm);
		if (err) {
			FAIL("Failed to send ecred connection request (err %d)\n", err);
		}
	} else {
		err = bt_l2cap_chan_connect(default_conn, &channel.chan, server.psm);
		if (err) {
			FAIL("Failed to send connection request (err %d)\n", err);
		}
	}
}

static void register_l2cap_server(void)
{
	int err;

	err = bt_l2cap_server_register(&server);
	if (err < 0) {
		FAIL("Failed to get free server (err %d)\n");
		return;
	}
}

static void connected(struct bt_conn *conn, uint8_t err)
{
	if (err) {
		FAIL("Failed to connect (err %d)\n", err);
		bt_conn_unref(default_conn);
		default_conn = NULL;
		return;
	}

	default_conn = bt_conn_ref(conn);

	SET_FLAG(is_connected);
}

static void disconnected(struct bt_conn *conn, uint8_t reason)
{
	if (default_conn != conn) {
		FAIL("Connection mismatch %p %p)\n", default_conn, conn);
		return;
	}

	bt_conn_unref(default_conn);
	default_conn = NULL;
	UNSET_FLAG(is_connected);
}

BT_CONN_CB_DEFINE(conn_callbacks) = {
	.connected = connected,
	.disconnected = disconnected,
};

static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
			 struct net_buf_simple *ad)
{
	struct bt_le_conn_param *param;
	int err;

	err = bt_le_scan_stop();
	if (err) {
		FAIL("Failed to stop scanning (err %d)\n", err);
		return;
	}

	param = BT_LE_CONN_PARAM_DEFAULT;
	err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, param, &default_conn);
	if (err) {
		FAIL("Failed to create connection (err %d)\n", err);
		return;
	}
}

static void test_peripheral_main(void)
{
	int err;
	const struct bt_data ad[] = {
		BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
	};

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

	register_l2cap_server();

	err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0);
	if (err != 0) {
		FAIL("Advertising failed to start (err %d)\n", err);
		return;
	}

	WAIT_FOR_FLAG_SET(is_connected);

	WAIT_FOR_FLAG_SET(chan_connected);

	WAIT_FOR_FLAG_SET(data_received);

	WAIT_FOR_FLAG_UNSET(is_connected);

	PASS("Test passed\n");
}

static void test_central_main(void)
{
	int err;

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

	err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found);
	if (err != 0) {
		FAIL("Scanning failed to start (err %d)\n", err);
	}

	WAIT_FOR_FLAG_SET(is_connected);

	connect_l2cap_channel();
	WAIT_FOR_FLAG_SET(chan_connected);

	WAIT_FOR_FLAG_SET(data_received);

	err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
	if (err) {
		FAIL("Failed to disconnect (err %d)\n", err);
		return;
	}

	WAIT_FOR_FLAG_UNSET(is_connected);

	PASS("Test passed\n");
}

static const struct bst_test_instance test_def[] = {
	{
		.test_id = "peripheral",
		.test_descr = "Peripheral",
		.test_post_init_f = test_init,
		.test_tick_f = test_tick,
		.test_main_f = test_peripheral_main,
	},
	{
		.test_id = "central",
		.test_descr = "Central",
		.test_post_init_f = test_init,
		.test_tick_f = test_tick,
		.test_main_f = test_central_main,
	},
	BSTEST_END_MARKER,
};

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