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

#include "utils.h"
#include "main.h"
#include "gatt_utils.h"

#include <zephyr/bluetooth/addr.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/settings/settings.h>
#include <zephyr/toolchain/gcc.h>

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

void set_public_addr(void)
{
	bt_addr_le_t addr = {BT_ADDR_LE_RANDOM,
			     {{0x0A, 0x89, 0x67, 0x45, 0x23, 0xC1}}};
	bt_id_create(&addr, NULL);
}

void server_round_0(void)
{
	struct bt_conn *conn;

	conn = connect_as_central();
	wait_for_client_read();

	printk("bonding\n");
	bond(conn);
}

void server_round_1(void)
{
	struct bt_conn *conn;

	/* Wait for GATT DB hash to complete. */
	k_sleep(K_SECONDS(2));
	conn = connect_as_central();
	printk("encrypting\n");
	set_security(conn, BT_SECURITY_L2);

	wait_for_client_read();
	wait_disconnected();

	printk("register second service, peer will be change-unaware\n");
	gatt_register_service_2();
	/* on-disk hash will be different when round 2 (and round 4)
	 * start, the peer will be marked as change-unaware
	 */
	k_sleep(K_MSEC(100));
}

void server_round_2(void)
{
	struct bt_conn *conn;

	conn = connect_as_central();
	printk("encrypting\n");
	set_security(conn, BT_SECURITY_L2);

	wait_for_client_read();

	/* Kill the power before the graceful disconnect, to make sure
	 * that the change-aware status has been written correctly to
	 * NVS. We still have to wait for the delayed work to be run.
	 */
	k_sleep(K_MSEC(CONFIG_BT_SETTINGS_DELAYED_STORE_MS));
}

void server_round_3(void)
{
	struct bt_conn *conn;

	conn = connect_as_central();
	printk("encrypting\n");
	set_security(conn, BT_SECURITY_L2);

	wait_for_client_read();
	wait_disconnected();

	printk("register second service, peer will be change-unaware\n");
	gatt_register_service_2();
	/* on-disk hash will be different when round 2 (and round 4)
	 * start, the peer will be marked as change-unaware
	 */
	k_sleep(K_MSEC(100));
}

void server_round_4(void)
{
	struct bt_conn *conn;

	conn = connect_as_central();
	printk("encrypting\n");
	set_security(conn, BT_SECURITY_L2);

	wait_for_client_read();
	wait_disconnected();
}

void server_round_5(void)
{
	gatt_register_service_2();

	/* sleep long enough to ensure the DB hash is stored to disk, but short
	 * enough to make sure the delayed storage work item is not executed.
	 */
	k_sleep(K_MSEC(100));
}

void server_round_6(void)
{
	struct bt_conn *conn;

	gatt_register_service_2();

	conn = connect_as_central();
	printk("encrypting\n");
	set_security(conn, BT_SECURITY_L2);

	wait_for_client_read();
	wait_disconnected();
}

/* What is being tested: since this deals with settings it's not the rounds
 * themselves, but rather the transitions that test expected behavior.
 *
 * Round 0 -> 1: test CCC / CF values written before bonding are stored to NVS
 * if the server reboots before disconnecting.
 *
 * Round 1 -> 2: test change-awareness is updated if GATT DB changes _after_ the
 * peer has disconnected. In round 2 we also make sure we receive the Service
 * Changed indication.
 *
 * Round 2 -> 3: tests `CONFIG_BT_SETTINGS_CF_STORE_ON_WRITE` does its job, and
 * writes the change-awareness before we get disconnected. Basically, this
 * transition simulates a user yanking the power of the device before it has the
 * chance to disconnect.
 *
 * Round 3 -> 4: same as (1->2), except this time we won't get the SC indication
 * (as we have unsubscribed from it). We should instead get the
 * `BT_ATT_ERR_DB_OUT_OF_SYNC` error on the first attribute read. This also
 * tests that robust GATT caching is enforced.
 *
 * Round 4 -> 5: tests change-awareness status is still written on disconnect.
 * This is a non-regression test to make sure we didn't break the previous
 * behavior.
 *
 * Round 5 -> 6: tests DFU corner case: in this case, we are on the first boot
 * of an updated firmware, that will register new services. But for some unknown
 * reason, we decide to reboot before the delayed store work item has had the
 * time to execute and store that the peers are now change-unaware. Round 6 then
 * makes sure that we are indeed change-unaware.
 */
void server_procedure(void)
{
	uint8_t round = get_test_round();

	wait_for_round_start();

	printk("Start test round: %d\n", get_test_round());

	/* Use the same public address for all instances of the central. If we
	 * don't do that, encryption (using the bond stored in NVS) will
	 * fail.
	 */
	set_public_addr();

	gatt_register_service_1();

	bt_enable(NULL);
	settings_load();

	switch (round) {
	case 0:
		server_round_0();
		break;
	case 1:
		server_round_1();
		break;
	case 2:
		server_round_2();
		break;
	case 3:
		server_round_3();
		break;
	case 4:
		server_round_4();
		break;
	case 5:
		server_round_5();
		break;
	case 6:
		server_round_6();
		break;
	default:
		FAIL("Round %d doesn't exist\n", round);
		break;
	}

	signal_next_test_round();
}
