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

#include <kernel.h>
#include <logging/log.h>
#include <settings/settings.h>
#include <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", log_strdup(path));

	ret = settings_delete(path);
	if (ret != 0) {
		LOG_ERR("Failed to remove setting %s, ret %d", log_strdup(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)
{
	int ret;

	ARG_UNUSED(aInstance);

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