/* Common functions for LE Audio services */

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

#include <zephyr/bluetooth/att.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/audio/audio.h>
#include <zephyr/bluetooth/audio/bap.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/check.h>

#include "audio_internal.h"

LOG_MODULE_REGISTER(bt_audio, CONFIG_BT_AUDIO_LOG_LEVEL);

#if defined(CONFIG_BT_CONN)

static uint8_t bt_audio_security_check(const struct bt_conn *conn)
{
	struct bt_conn_info info;
	int err;

	err = bt_conn_get_info(conn, &info);
	if (err < 0) {
		return BT_ATT_ERR_UNLIKELY;
	}

	/* Require an encryption key with at least 128 bits of entropy, derived from SC or OOB
	 * method.
	 */
	if ((info.security.flags & (BT_SECURITY_FLAG_OOB | BT_SECURITY_FLAG_SC)) == 0) {
		/* If the client has insufficient security to read/write the requested attribute
		 * then an ATT_ERROR_RSP PDU shall be sent with the Error Code parameter set to
		 * Insufficient Authentication (0x05).
		 */
		return BT_ATT_ERR_AUTHENTICATION;
	}

	if (info.security.enc_key_size < BT_ENC_KEY_SIZE_MAX) {
		return BT_ATT_ERR_ENCRYPTION_KEY_SIZE;
	}

	return BT_ATT_ERR_SUCCESS;
}

ssize_t bt_audio_read_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr,
			   void *buf, uint16_t len, uint16_t offset)
{
	const struct bt_audio_attr_user_data *user_data = attr->user_data;

	if (user_data->read == NULL) {
		return BT_GATT_ERR(BT_ATT_ERR_READ_NOT_PERMITTED);
	}

	if (conn != NULL) {
		uint8_t err;

		err = bt_audio_security_check(conn);
		if (err != 0) {
			return BT_GATT_ERR(err);
		}
	}

	return user_data->read(conn, attr, buf, len, offset);
}

ssize_t bt_audio_write_chrc(struct bt_conn *conn, const struct bt_gatt_attr *attr,
			    const void *buf, uint16_t len, uint16_t offset, uint8_t flags)
{
	const struct bt_audio_attr_user_data *user_data = attr->user_data;

	if (user_data->write == NULL) {
		return BT_GATT_ERR(BT_ATT_ERR_WRITE_NOT_PERMITTED);
	}

	if (conn != NULL) {
		uint8_t err;

		err = bt_audio_security_check(conn);
		if (err != 0) {
			return BT_GATT_ERR(err);
		}
	}

	return user_data->write(conn, attr, buf, len, offset, flags);
}

ssize_t bt_audio_ccc_cfg_write(struct bt_conn *conn, const struct bt_gatt_attr *attr,
			       uint16_t value)
{
	if (conn != NULL) {
		uint8_t err;

		err = bt_audio_security_check(conn);
		if (err != 0) {
			return BT_GATT_ERR(err);
		}
	}

	return sizeof(value);
}
#endif /* CONFIG_BT_CONN */

/* Broadcast sink depends on Scan Delegator, so we can just guard it with the Scan Delegator */
#if defined(CONFIG_BT_BAP_SCAN_DELEGATOR)

static int decode_codec_ltv(struct net_buf_simple *buf,
			    struct bt_codec_data *codec_data)
{
	void *value;

	if (buf->len < sizeof(codec_data->data.data_len)) {
		LOG_DBG("Not enough data for LTV length field: %u", buf->len);

		return -ENOMEM;
	}

	codec_data->data.data_len = net_buf_simple_pull_u8(buf);

	if (buf->len < sizeof(codec_data->data.type)) {
		LOG_DBG("Not enough data for LTV type field: %u", buf->len);

		return -EMSGSIZE;
	}

	/* LTV structures include the data.type in the length field,
	 * but we do not do that for the bt_data struct in Zephyr
	 */
	codec_data->data.data_len -= sizeof(codec_data->data.type);

	codec_data->data.type = net_buf_simple_pull_u8(buf);

	codec_data->data.data = codec_data->value;

	if (buf->len < codec_data->data.data_len) {
		LOG_DBG("Not enough data for LTV value field: %u/%zu", buf->len,
			codec_data->data.data_len);

		return -EMSGSIZE;
	}

	value = net_buf_simple_pull_mem(buf, codec_data->data.data_len);
	(void)memcpy(codec_data->value, value, codec_data->data.data_len);

	return 0;
}

static int decode_bis_data(struct net_buf_simple *buf, struct bt_bap_base_bis_data *bis)
{
	uint8_t len;

	if (buf->len < BT_BAP_BASE_BIS_DATA_MIN_SIZE) {
		LOG_DBG("Not enough bytes (%u) to decode BIS data", buf->len);

		return -ENOMEM;
	}

	bis->index = net_buf_simple_pull_u8(buf);
	if (!IN_RANGE(bis->index, BT_ISO_BIS_INDEX_MIN, BT_ISO_BIS_INDEX_MAX)) {
		LOG_DBG("Invalid BIS index %u", bis->index);

		return -EINVAL;
	}

	/* codec config data length */
	len = net_buf_simple_pull_u8(buf);
	if (len > buf->len) {
		LOG_DBG("Invalid BIS specific codec config data length: %u (buf is %u)", len,
			buf->len);

		return -EMSGSIZE;
	}

	if (len > 0) {
		struct net_buf_simple ltv_buf;
		void *ltv_data;

		/* Use an extra net_buf_simple to be able to decode until it
		 * is empty (len = 0)
		 */
		ltv_data = net_buf_simple_pull_mem(buf, len);
		net_buf_simple_init_with_data(&ltv_buf, ltv_data, len);


		while (ltv_buf.len != 0) {
			struct bt_codec_data *bis_codec_data;
			int err;

			if (bis->data_count >= ARRAY_SIZE(bis->data)) {
				LOG_WRN("BIS data overflow; discarding");
				break;
			}

			bis_codec_data = &bis->data[bis->data_count];

			err = decode_codec_ltv(&ltv_buf, bis_codec_data);
			if (err != 0) {
				LOG_DBG("Failed to decode BIS config data for entry[%u]: %d",
					bis->data_count, err);

				return err;
			}

			bis->data_count++;
		}
	}

	return 0;
}

static int decode_subgroup(struct net_buf_simple *buf, struct bt_bap_base_subgroup *subgroup)
{
	struct net_buf_simple ltv_buf;
	struct bt_codec	*codec;
	void *ltv_data;
	uint8_t len;

	codec = &subgroup->codec;

	subgroup->bis_count = net_buf_simple_pull_u8(buf);
	if (subgroup->bis_count > ARRAY_SIZE(subgroup->bis_data)) {
		LOG_DBG("BASE has more BIS %u than we support %u", subgroup->bis_count,
			(uint8_t)ARRAY_SIZE(subgroup->bis_data));

		return -ENOMEM;
	}

	codec->id = net_buf_simple_pull_u8(buf);
	codec->cid = net_buf_simple_pull_le16(buf);
	codec->vid = net_buf_simple_pull_le16(buf);

	/* codec configuration data length */
	len = net_buf_simple_pull_u8(buf);
	if (len > buf->len) {
		LOG_DBG("Invalid codec config data length: %u (buf is %u)", len, buf->len);

		return -EINVAL;
	}

#if CONFIG_BT_CODEC_MAX_DATA_COUNT > 0
	/* Use an extra net_buf_simple to be able to decode until it
	 * is empty (len = 0)
	 */
	ltv_data = net_buf_simple_pull_mem(buf, len);
	net_buf_simple_init_with_data(&ltv_buf, ltv_data, len);

	/* The loop below is very similar to codec_config_store with notable
	 * exceptions that it can do early termination, and also does not log
	 * every LTV entry, which would simply be too much for handling
	 * broadcasted BASEs
	 */
	while (ltv_buf.len != 0) {
		struct bt_codec_data *codec_data;
		int err;

		if (codec->data_count >= ARRAY_SIZE(codec->data)) {
			LOG_WRN("BIS codec data overflow; discarding");
			break;
		}

		codec_data = &codec->data[codec->data_count];

		err = decode_codec_ltv(&ltv_buf, codec_data);
		if (err != 0) {
			LOG_DBG("Failed to decode codec config data for entry %u: %d",
				codec->data_count, err);

			return err;
		}

		codec->data_count++;
	}

	if (buf->len < sizeof(len)) {
		LOG_DBG("Cannot store BASE in buffer");

		return -ENOMEM;
	}
#else /* CONFIG_BT_CODEC_MAX_DATA_COUNT == 0 */
	if (len > 0) {
		LOG_DBG("Cannot store codec config data");

		return -ENOMEM;
	}
#endif /* CONFIG_BT_CODEC_MAX_DATA_COUNT */

	/* codec metadata length */
	len = net_buf_simple_pull_u8(buf);
	if (len > buf->len) {
		LOG_DBG("Invalid codec config data length: %u (buf is %u)", len, buf->len);

		return -EMSGSIZE;
	}

#if CONFIG_BT_CODEC_MAX_METADATA_COUNT > 0
	/* Use an extra net_buf_simple to be able to decode until it
	 * is empty (len = 0)
	 */
	ltv_data = net_buf_simple_pull_mem(buf, len);
	net_buf_simple_init_with_data(&ltv_buf, ltv_data, len);

	/* The loop below is very similar to codec_config_store with notable
	 * exceptions that it can do early termination, and also does not log
	 * every LTV entry, which would simply be too much for handling
	 * broadcasted BASEs
	 */
	while (ltv_buf.len != 0) {
		struct bt_codec_data *metadata;
		int err;

		if (codec->meta_count >= ARRAY_SIZE(codec->meta)) {
			LOG_WRN("BIS codec metadata overflow; discarding");
			break;
		}

		metadata = &codec->meta[codec->meta_count];

		err = decode_codec_ltv(&ltv_buf, metadata);
		if (err != 0) {
			LOG_DBG("Failed to decode codec metadata for entry %u: %d",
				codec->meta_count, err);

			return err;
		}

		codec->meta_count++;
	}
#else /* CONFIG_BT_CODEC_MAX_METADATA_COUNT == 0 */
	if (len > 0) {
		LOG_DBG("Cannot store metadata");

		return -ENOMEM;
	}
#endif /* CONFIG_BT_CODEC_MAX_METADATA_COUNT */

	for (size_t i = 0U; i < subgroup->bis_count; i++) {
		const int err = decode_bis_data(buf, &subgroup->bis_data[i]);

		if (err != 0) {
			LOG_DBG("Failed to decode BIS data for bis[%zu]: %d", i, err);

			return err;
		}
	}

	return 0;
}

int bt_bap_decode_base(struct bt_data *data, struct bt_bap_base *base)
{
	struct bt_uuid_16 broadcast_uuid;
	struct net_buf_simple net_buf;
	void *uuid;

	CHECKIF(data == NULL) {
		LOG_DBG("data is NULL");

		return -EINVAL;
	}

	CHECKIF(base == NULL) {
		LOG_DBG("base is NULL");

		return -EINVAL;
	}

	if (data->type != BT_DATA_SVC_DATA16) {
		LOG_DBG("Invalid type: %u", data->type);

		return -ENOMSG;
	}

	if (data->data_len < BT_BAP_BASE_MIN_SIZE) {
		return -EMSGSIZE;
	}

	net_buf_simple_init_with_data(&net_buf, (void *)data->data,
				      data->data_len);

	uuid = net_buf_simple_pull_mem(&net_buf, BT_UUID_SIZE_16);
	if (!bt_uuid_create(&broadcast_uuid.uuid, uuid, BT_UUID_SIZE_16)) {
		LOG_ERR("bt_uuid_create failed");

		return -EINVAL;
	}

	if (bt_uuid_cmp(&broadcast_uuid.uuid, BT_UUID_BASIC_AUDIO) != 0) {
		LOG_DBG("Invalid UUID");

		return -ENOMSG;
	}

	base->pd = net_buf_simple_pull_le24(&net_buf);
	base->subgroup_count = net_buf_simple_pull_u8(&net_buf);

	if (base->subgroup_count > ARRAY_SIZE(base->subgroups)) {
		LOG_DBG("Cannot decode BASE with %u subgroups (max supported is %zu)",
			base->subgroup_count, ARRAY_SIZE(base->subgroups));

		return -ENOMEM;
	}

	for (size_t i = 0U; i < base->subgroup_count; i++) {
		const int err = decode_subgroup(&net_buf, &base->subgroups[i]);

		if (err != 0) {
			LOG_DBG("Failed to decode subgroup[%zu]: %d", i, err);

			return err;
		}
	}

	return 0;
}
#endif /* CONFIG_BT_BAP_SCAN_DELEGATOR */

ssize_t bt_audio_codec_data_to_buf(const struct bt_codec_data *codec_data, size_t count,
				   uint8_t *buf, size_t buf_size)
{
	size_t total_len = 0;

	for (size_t i = 0; i < count; i++) {
		const struct bt_data *ltv = &codec_data[i].data;
		const uint8_t length = ltv->data_len;
		const uint8_t type = ltv->type;
		const uint8_t *value = ltv->data;
		const size_t ltv_len = sizeof(length) + sizeof(type) + length;

		/* Verify that the buffer can hold the next LTV structure */
		if (buf_size < total_len + ltv_len) {
			return -ENOMEM;
		}

		/* Copy data */
		buf[total_len++] = length + sizeof(type);
		buf[total_len++] = type;
		(void)memcpy(&buf[total_len], value, length);

		total_len += length;
	}

	return total_len;
}
