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

#include <errno.h>
#include <stdint.h>
#include <zephyr/sys/check.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(bt_ias_client, CONFIG_BT_IAS_CLIENT_LOG_LEVEL);

#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/services/ias.h>

enum {
	IAS_DISCOVER_IN_PROGRESS,

	IAS_NUM_FLAGS, /* keep as last */
};

struct bt_ias_client {
	/* Handle for alert writes */
	uint16_t alert_level_handle;

	/** Internal flags **/
	ATOMIC_DEFINE(flags, IAS_NUM_FLAGS);

	/* Gatt discover procedure parameters */
	struct bt_gatt_discover_params discover;
};

static const struct bt_uuid *alert_lvl_uuid = BT_UUID_ALERT_LEVEL;
static const struct bt_uuid *ias_uuid = BT_UUID_IAS;

static const struct bt_ias_client_cb *ias_client_cb;
static struct bt_ias_client client_list[CONFIG_BT_MAX_CONN];

static struct bt_ias_client *client_by_conn(struct bt_conn *conn)
{
	return &client_list[bt_conn_index(conn)];
}

static void client_cleanup(struct bt_ias_client *ias_client)
{
	(void)memset(ias_client, 0, sizeof(*ias_client));
}

static void discover_complete(struct bt_conn *conn, int err)
{
	LOG_DBG("conn %p", (void *)conn);

	if (err) {
		client_cleanup(client_by_conn(conn));
		LOG_DBG("Discover failed (err %d\n)", err);
	}

	if (ias_client_cb != NULL && ias_client_cb->discover != NULL) {
		ias_client_cb->discover(conn, err);
	}
}

int bt_ias_client_alert_write(struct bt_conn *conn, enum bt_ias_alert_lvl lvl)
{
	int err;
	uint8_t lvl_u8;

	CHECKIF(conn == NULL) {
		return -ENOTCONN;
	}

	if (client_by_conn(conn)->alert_level_handle == 0) {
		return -EINVAL;
	}

	lvl_u8 = (uint8_t)lvl;

	if (lvl_u8 < BT_IAS_ALERT_LVL_NO_ALERT || lvl_u8 > BT_IAS_ALERT_LVL_HIGH_ALERT) {
		LOG_ERR("Invalid alert value: %u", lvl_u8);
		return -EINVAL;
	}

	err = bt_gatt_write_without_response(conn,
					     client_by_conn(conn)->alert_level_handle,
					     &lvl_u8, sizeof(lvl_u8), false);
	if (err < 0) {
		LOG_ERR("IAS client level %d write failed: %d", lvl, err);
	}

	return err;
}

static uint8_t bt_ias_alert_lvl_disc_cb(struct bt_conn *conn,
					const struct bt_gatt_attr *attr,
					struct bt_gatt_discover_params *discover)
{
	const struct bt_gatt_chrc *chrc;

	atomic_clear_bit(client_by_conn(conn)->flags, IAS_DISCOVER_IN_PROGRESS);

	if (attr == NULL) {
		discover_complete(conn, -ENOENT);

		return BT_GATT_ITER_STOP;
	}

	chrc = (struct bt_gatt_chrc *)attr->user_data;

	client_by_conn(conn)->alert_level_handle = chrc->value_handle;
	discover_complete(conn, 0);

	return BT_GATT_ITER_STOP;
}

static uint8_t bt_ias_prim_disc_cb(struct bt_conn *conn,
				   const struct bt_gatt_attr *attr,
				   struct bt_gatt_discover_params *discover)
{
	int err;
	const struct bt_gatt_service_val *data;
	struct bt_ias_client *client = client_by_conn(conn);

	if (!attr) {
		discover_complete(conn, -ENOENT);

		return BT_GATT_ITER_STOP;
	}

	data = attr->user_data;

	client->discover.uuid = alert_lvl_uuid;
	client->discover.start_handle = attr->handle + 1;
	client->discover.end_handle = data->end_handle;
	client->discover.type = BT_GATT_DISCOVER_CHARACTERISTIC;
	client->discover.func = bt_ias_alert_lvl_disc_cb;

	err = bt_gatt_discover(conn, &client->discover);
	if (err) {
		discover_complete(conn, err);
	}

	return BT_GATT_ITER_STOP;
}

int bt_ias_discover(struct bt_conn *conn)
{
	int err;
	struct bt_ias_client *client = client_by_conn(conn);

	CHECKIF(!conn || !ias_client_cb || !ias_client_cb->discover) {
		return -EINVAL;
	}

	if (atomic_test_bit(client->flags, IAS_DISCOVER_IN_PROGRESS)) {
		return -EBUSY;
	}

	client_cleanup(client);
	atomic_set_bit(client->flags, IAS_DISCOVER_IN_PROGRESS);

	client->discover.uuid = ias_uuid;
	client->discover.func = bt_ias_prim_disc_cb;
	client->discover.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
	client->discover.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
	client->discover.type = BT_GATT_DISCOVER_PRIMARY;

	err = bt_gatt_discover(conn, &client->discover);
	if (err < 0) {
		discover_complete(conn, err);
	}

	return err;
}

int bt_ias_client_cb_register(const struct bt_ias_client_cb *cb)
{
	CHECKIF(!cb) {
		return -EINVAL;
	}

	CHECKIF(cb->discover == NULL) {
		return -EINVAL;
	}

	CHECKIF(ias_client_cb) {
		return -EALREADY;
	}

	ias_client_cb = cb;

	return 0;
}
