/*
 * 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 = (struct bt_gatt_chrc *)attr->user_data;

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

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

		return BT_GATT_ITER_STOP;
	}

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