/*
 * 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 <sys/dlist.h>
#include <sys/byteorder.h>

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

#include <logging/log.h>

LOG_MODULE_DECLARE(bt_ots, CONFIG_BT_OTS_LOG_LEVEL);

/**Start of the usable range of Object IDs (values 0 to 0x100 are reserved)*/
#define OTS_OBJ_ID_START_RANGE  0x000000000100

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 - OTS_OBJ_ID_START_RANGE + 1;
		}
	} else {
		return id - OTS_OBJ_ID_START_RANGE;
	}
}

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 OTS_OBJ_ID_START_RANGE + index - 1;
		}
	} else {
		return OTS_OBJ_ID_START_RANGE + 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 < OTS_OBJ_ID_START_RANGE &&
	    (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;
}
