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

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

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