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

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

	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)
{
	int ret;
	char subtree[OT_SETTINGS_MAX_PATH_LEN];
	struct ot_setting_delete_ctx delete_ctx = {
		.subtree = subtree,
		.status = -ENOENT,
		.target_index = index
	};

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

	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.");

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

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