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

#include <zephyr/types.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <zephyr/sys/dlist.h>
#include <zephyr/sys/byteorder.h>

#include <zephyr/bluetooth/services/ots.h>
#include "ots_internal.h"

#include <zephyr/logging/log.h>

LOG_MODULE_DECLARE(bt_ots, CONFIG_BT_OTS_LOG_LEVEL);


struct bt_gatt_ots_pool_item {
	sys_dnode_t dnode;
	struct bt_gatt_ots_object val;
	bool is_allocated;
};

struct bt_gatt_ots_obj_manager {
	sys_dlist_t list;
	struct bt_gatt_ots_pool_item pool[CONFIG_BT_OTS_MAX_OBJ_CNT];
	bool is_assigned;
};

static uint64_t obj_id_to_index(uint64_t id)
{
	if (IS_ENABLED(CONFIG_BT_OTS_DIR_LIST_OBJ)) {
		if (id == OTS_OBJ_ID_DIR_LIST) {
			return id;
		} else {
			return id - BT_OTS_OBJ_ID_MIN + 1;
		}
	} else {
		return id - BT_OTS_OBJ_ID_MIN;
	}
}

static uint64_t obj_index_to_id(uint64_t index)
{
	if (IS_ENABLED(CONFIG_BT_OTS_DIR_LIST_OBJ)) {
		if (index == 0) {
			return OTS_OBJ_ID_DIR_LIST;
		} else {
			return BT_OTS_OBJ_ID_MIN + index - 1;
		}
	} else {
		return BT_OTS_OBJ_ID_MIN + index;
	}
}

int bt_gatt_ots_obj_manager_first_obj_get(
	struct bt_gatt_ots_obj_manager *obj_manager,
	struct bt_gatt_ots_object **obj)
{
	sys_dnode_t *obj_dnode;
	struct bt_gatt_ots_pool_item *first_item;

	if (sys_dlist_is_empty(&obj_manager->list)) {
		return -ENOENT;
	}

	obj_dnode = sys_dlist_peek_head_not_empty(&obj_manager->list);
	first_item = CONTAINER_OF(obj_dnode, struct bt_gatt_ots_pool_item,
				  dnode);
	*obj = &first_item->val;

	return 0;
}

int bt_gatt_ots_obj_manager_last_obj_get(
	struct bt_gatt_ots_obj_manager *obj_manager,
	struct bt_gatt_ots_object **obj)
{
	sys_dnode_t *obj_dnode;
	struct bt_gatt_ots_pool_item *last_item;

	if (sys_dlist_is_empty(&obj_manager->list)) {
		return -ENOENT;
	}

	obj_dnode = sys_dlist_peek_tail(&obj_manager->list);
	last_item = CONTAINER_OF(obj_dnode, struct bt_gatt_ots_pool_item,
				 dnode);
	*obj = &last_item->val;

	return 0;
}

int bt_gatt_ots_obj_manager_prev_obj_get(
	struct bt_gatt_ots_obj_manager *obj_manager,
	const struct bt_gatt_ots_object *cur_obj,
	struct bt_gatt_ots_object **prev_obj)
{
	sys_dnode_t *prev_obj_dnode;
	struct bt_gatt_ots_pool_item *cur_item, *prev_item;

	if (sys_dlist_is_empty(&obj_manager->list)) {
		return -ENOENT;
	}

	cur_item = CONTAINER_OF(cur_obj, struct bt_gatt_ots_pool_item, val);
	prev_obj_dnode = sys_dlist_peek_prev_no_check(&obj_manager->list,
						      &cur_item->dnode);
	if (!prev_obj_dnode) {
		return -ENFILE;
	}

	prev_item = CONTAINER_OF(prev_obj_dnode,
				 struct bt_gatt_ots_pool_item,
				 dnode);
	*prev_obj = &prev_item->val;

	return 0;
}

int bt_gatt_ots_obj_manager_next_obj_get(
	struct bt_gatt_ots_obj_manager *obj_manager,
	const struct bt_gatt_ots_object *cur_obj,
	struct bt_gatt_ots_object **next_obj)
{
	sys_dnode_t *next_obj_dnode;
	struct bt_gatt_ots_pool_item *cur_item, *next_item;

	if (sys_dlist_is_empty(&obj_manager->list)) {
		return -ENOENT;
	}

	cur_item = CONTAINER_OF(cur_obj, struct bt_gatt_ots_pool_item, val);
	next_obj_dnode = sys_dlist_peek_next_no_check(&obj_manager->list,
						      &cur_item->dnode);
	if (!next_obj_dnode) {
		return -ENFILE;
	}

	next_item = CONTAINER_OF(next_obj_dnode,
				 struct bt_gatt_ots_pool_item,
				 dnode);
	*next_obj = &next_item->val;

	return 0;
}

int bt_gatt_ots_obj_manager_obj_get(
	struct bt_gatt_ots_obj_manager *obj_manager, uint64_t id,
	struct bt_gatt_ots_object **object)
{
	uint64_t index;

	if (sys_dlist_is_empty(&obj_manager->list)) {
		return -ENOENT;
	}

	if (id < BT_OTS_OBJ_ID_MIN &&
	    (IS_ENABLED(CONFIG_BT_OTS_DIR_LIST_OBJ) &&
		id != OTS_OBJ_ID_DIR_LIST)) {
		return -EINVAL;
	}

	index = obj_id_to_index(id);

	if (index >= ARRAY_SIZE(obj_manager->pool)) {
		return -EINVAL;
	}

	if (!obj_manager->pool[index].is_allocated) {
		return -EINVAL;
	}

	*object = &obj_manager->pool[index].val;

	return 0;
}

int bt_gatt_ots_obj_manager_obj_add(
	struct bt_gatt_ots_obj_manager *obj_manager,
	struct bt_gatt_ots_object **object)
{
	for (uint64_t i = 0; i < ARRAY_SIZE(obj_manager->pool); i++) {
		struct bt_gatt_ots_pool_item *cur_obj =
			&obj_manager->pool[i];

		if (!cur_obj->is_allocated) {
			cur_obj->is_allocated = true;
			cur_obj->val.id = obj_index_to_id(i);
			sys_dlist_append(&obj_manager->list, &cur_obj->dnode);

			*object = &cur_obj->val;
			return 0;
		}
	}

	return -ENOMEM;
}

int bt_gatt_ots_obj_manager_obj_delete(struct bt_gatt_ots_object *obj)
{
	struct bt_gatt_ots_pool_item *item;

	item = CONTAINER_OF(obj, struct bt_gatt_ots_pool_item, val);

	if (!item->is_allocated) {
		return -EINVAL;
	}

	if (IS_ENABLED(CONFIG_BT_OTS_DIR_LIST_OBJ) &&
	    obj->id == OTS_OBJ_ID_DIR_LIST) {
		return -EINVAL;
	}

	item->is_allocated = false;
	sys_dlist_remove(&item->dnode);

	return 0;
}


bool bt_gatt_ots_obj_manager_obj_contains(struct bt_gatt_ots_obj_manager *obj_manager,
					  struct bt_gatt_ots_object *obj)
{
	struct bt_gatt_ots_pool_item *item;

	item = CONTAINER_OF(obj, struct bt_gatt_ots_pool_item, val);

	return PART_OF_ARRAY(obj_manager->pool, item);
}

void *bt_gatt_ots_obj_manager_assign(void)
{
	static struct bt_gatt_ots_obj_manager
		obj_manager[CONFIG_BT_OTS_MAX_INST_CNT];
	struct bt_gatt_ots_obj_manager *cur_manager;


	for (cur_manager = obj_manager;
	     cur_manager != obj_manager + CONFIG_BT_OTS_MAX_INST_CNT;
	     cur_manager++) {
		if (!cur_manager->is_assigned) {
			break;
		}
	}

	if (cur_manager->is_assigned) {
		return NULL;
	}

	cur_manager->is_assigned = true;
	sys_dlist_init(&cur_manager->list);

	return cur_manager;
}
