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

#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/settings/settings.h>
#include <zephyr/random/rand32.h>

#include <openthread/platform/settings.h>

LOG_MODULE_REGISTER(net_otPlat_settings, CONFIG_OPENTHREAD_L2_LOG_LEVEL);

#define OT_SETTINGS_ROOT_KEY "ot"
#define OT_SETTINGS_MAX_PATH_LEN 32

struct ot_setting_delete_ctx {
	/* Setting subtree to delete. */
	const char *subtree;

	/* Current entry index, used to iterate over multiple setting
	 * instances.
	 */
	int index;

	/* Target index to delete. -1 to delete entire subtree. */
	int target_index;

	/* Operation result. */
	int status;

	/* Indicates if delete subtree root. */
	bool delete_subtree_root;
};

static int ot_setting_delete_cb(const char *key, size_t len,
				settings_read_cb read_cb, void *cb_arg,
				void *param)
{
	int ret;
	char path[OT_SETTINGS_MAX_PATH_LEN];
	struct ot_setting_delete_ctx *ctx =
		(struct ot_setting_delete_ctx *)param;

	ARG_UNUSED(len);
	ARG_UNUSED(read_cb);
	ARG_UNUSED(cb_arg);

	if ((ctx->target_index != -1) && (ctx->target_index != ctx->index)) {
		ctx->index++;
		return 0;
	}

	if (key == NULL && ctx->delete_subtree_root == false) {
		return 0;
	}

	ret = snprintk(path, sizeof(path), "%s%s%s", ctx->subtree,
		       key ? "/" : "", key ? key : "");
	__ASSERT(ret < sizeof(path), "Setting path buffer too small.");

	LOG_DBG("Removing: %s", path);

	ret = settings_delete(path);
	if (ret != 0) {
		LOG_ERR("Failed to remove setting %s, ret %d", path,
			ret);
		__ASSERT_NO_MSG(false);
	}

	ctx->status = 0;

	if (ctx->target_index == ctx->index) {
		/* Break the loop on index match, otherwise it was -1
		 * (delete all).
		 */
		return 1;
	}

	return 0;
}

static int ot_setting_delete_subtree(int key, int index, bool delete_subtree_root)
{
	int ret;
	char subtree[OT_SETTINGS_MAX_PATH_LEN];
	struct ot_setting_delete_ctx delete_ctx = {
		.subtree = subtree,
		.status = -ENOENT,
		.target_index = index,
		.delete_subtree_root = delete_subtree_root,
	};

	if (key == -1) {
		ret = snprintk(subtree, sizeof(subtree), "%s",
			       OT_SETTINGS_ROOT_KEY);
	} else {
		ret = snprintk(subtree, sizeof(subtree), "%s/%x",
			       OT_SETTINGS_ROOT_KEY, key);
	}
	__ASSERT(ret < sizeof(subtree), "Setting path buffer too small.");

	ret = settings_load_subtree_direct(subtree, ot_setting_delete_cb,
					   &delete_ctx);
	if (ret != 0) {
		LOG_ERR("Failed to delete OT subtree %s, index %d, ret %d",
			subtree, index, ret);
		__ASSERT_NO_MSG(false);
	}

	return delete_ctx.status;
}

static int ot_setting_exists_cb(const char *key, size_t len,
				settings_read_cb read_cb, void *cb_arg,
				void *param)
{
	bool *exists = (bool *)param;

	ARG_UNUSED(len);
	ARG_UNUSED(read_cb);
	ARG_UNUSED(cb_arg);
	ARG_UNUSED(key);

	*exists = true;

	return 1;
}

static bool ot_setting_exists(const char *path)
{
	bool exists = false;

	(void)settings_load_subtree_direct(path, ot_setting_exists_cb, &exists);

	return exists;
}

struct ot_setting_read_ctx {
	/* Buffer for the setting. */
	uint8_t *value;

	/* Buffer length on input, setting length read on output. */
	uint16_t *length;

	/* Current entry index, used to iterate over multiple setting
	 * instances.
	 */
	int index;

	/* Target instance to read. */
	int target_index;

	/* Operation result. */
	int status;
};

static int ot_setting_read_cb(const char *key, size_t len,
			      settings_read_cb read_cb, void *cb_arg,
			      void *param)
{
	int ret;
	struct ot_setting_read_ctx *ctx = (struct ot_setting_read_ctx *)param;

	ARG_UNUSED(len);
	ARG_UNUSED(read_cb);
	ARG_UNUSED(cb_arg);

	if (ctx->target_index != ctx->index) {
		ctx->index++;
		return 0;
	}

	/* Found setting, break the loop. */

	if ((ctx->value == NULL) || (ctx->length == NULL)) {
		goto out;
	}

	if (*(ctx->length) < len) {
		len = *(ctx->length);
	}

	ret = read_cb(cb_arg, ctx->value, len);
	if (ret <= 0) {
		LOG_ERR("Failed to read the setting, ret: %d", ret);
		ctx->status = -EIO;
		return 1;
	}

out:
	if (ctx->length != NULL) {
		*(ctx->length) = len;
	}

	ctx->status = 0;

	return 1;
}

/* OpenThread APIs */

void otPlatSettingsInit(otInstance *aInstance, const uint16_t *aSensitiveKeys,
			uint16_t aSensitiveKeysLength)
{
	int ret;

	ARG_UNUSED(aInstance);
	ARG_UNUSED(aSensitiveKeys);
	ARG_UNUSED(aSensitiveKeysLength);

	ret = settings_subsys_init();
	if (ret != 0) {
		LOG_ERR("settings_subsys_init failed (ret %d)", ret);
	}
}

otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex,
			  uint8_t *aValue, uint16_t *aValueLength)
{
	int ret;
	char path[OT_SETTINGS_MAX_PATH_LEN];
	struct ot_setting_read_ctx read_ctx = {
		.value = aValue,
		.length = (uint16_t *)aValueLength,
		.status = -ENOENT,
		.target_index = aIndex
	};

	ARG_UNUSED(aInstance);

	LOG_DBG("%s Entry aKey %u aIndex %d", __func__, aKey, aIndex);

	ret = snprintk(path, sizeof(path), "%s/%x", OT_SETTINGS_ROOT_KEY, aKey);
	__ASSERT(ret < sizeof(path), "Setting path buffer too small.");

	ret = settings_load_subtree_direct(path, ot_setting_read_cb, &read_ctx);
	if (ret != 0) {
		LOG_ERR("Failed to load OT setting aKey %d, aIndex %d, ret %d",
			aKey, aIndex, ret);
	}

	if (read_ctx.status != 0) {
		LOG_DBG("aKey %u aIndex %d not found", aKey, aIndex);
		return OT_ERROR_NOT_FOUND;
	}

	return OT_ERROR_NONE;
}

otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey,
			  const uint8_t *aValue, uint16_t aValueLength)
{
	int ret;
	char path[OT_SETTINGS_MAX_PATH_LEN];

	ARG_UNUSED(aInstance);

	LOG_DBG("%s Entry aKey %u", __func__, aKey);

	(void)ot_setting_delete_subtree(aKey, -1, false);

	ret = snprintk(path, sizeof(path), "%s/%x", OT_SETTINGS_ROOT_KEY, aKey);
	__ASSERT(ret < sizeof(path), "Setting path buffer too small.");

	ret = settings_save_one(path, aValue, aValueLength);
	if (ret != 0) {
		LOG_ERR("Failed to store setting %d, ret %d", aKey, ret);
		return OT_ERROR_NO_BUFS;
	}

	return OT_ERROR_NONE;
}

otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey,
			  const uint8_t *aValue, uint16_t aValueLength)
{
	int ret;
	char path[OT_SETTINGS_MAX_PATH_LEN];

	ARG_UNUSED(aInstance);

	LOG_DBG("%s Entry aKey %u", __func__, aKey);

	do {
		ret = snprintk(path, sizeof(path), "%s/%x/%08x",
			       OT_SETTINGS_ROOT_KEY, aKey, sys_rand32_get());
		__ASSERT(ret < sizeof(path), "Setting path buffer too small.");
	} while (ot_setting_exists(path));

	ret = settings_save_one(path, aValue, aValueLength);
	if (ret != 0) {
		LOG_ERR("Failed to store setting %d, ret %d", aKey, ret);
		return OT_ERROR_NO_BUFS;
	}

	return OT_ERROR_NONE;
}

otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex)
{
	int ret;

	ARG_UNUSED(aInstance);

	LOG_DBG("%s Entry aKey %u aIndex %d", __func__, aKey, aIndex);

	ret = ot_setting_delete_subtree(aKey, aIndex, true);
	if (ret != 0) {
		LOG_DBG("Entry not found aKey %u aIndex %d", aKey, aIndex);
		return OT_ERROR_NOT_FOUND;
	}

	return OT_ERROR_NONE;
}

void otPlatSettingsWipe(otInstance *aInstance)
{
	ARG_UNUSED(aInstance);

	(void)ot_setting_delete_subtree(-1, -1, true);
}

void otPlatSettingsDeinit(otInstance *aInstance)
{
	ARG_UNUSED(aInstance);
}
