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

#include <zephyr/settings/settings.h>
#include <zephyr/shell/shell.h>
#include <zephyr/sys/util.h>
#include <zephyr/toolchain.h>

#include <stdint.h>
#include <stddef.h>

struct settings_list_callback_params {
	const struct shell *shell_ptr;
	const char *subtree;
};

static int settings_list_callback(const char      *key,
				  size_t len,
				  settings_read_cb read_cb,
				  void            *cb_arg,
				  void            *param)
{
	ARG_UNUSED(len);
	ARG_UNUSED(read_cb);
	ARG_UNUSED(cb_arg);

	struct settings_list_callback_params *params = param;

	if (params->subtree != NULL) {
		shell_print(params->shell_ptr, "%s/%s", params->subtree, key);
	} else {
		shell_print(params->shell_ptr, "%s", key);
	}

	return 0;
}

static int cmd_list(const struct shell *shell_ptr, size_t argc, char *argv[])
{
	int err;

	struct settings_list_callback_params params = {
		.shell_ptr = shell_ptr,
		.subtree = (argc == 2 ? argv[1] : NULL)
	};

	err = settings_load_subtree_direct(params.subtree, settings_list_callback, &params);

	if (err) {
		shell_error(shell_ptr, "Failed to load settings: %d", err);
	}

	return err;
}

struct settings_read_callback_params {
	const struct shell *shell_ptr;
	bool value_found;
};

static int settings_read_callback(const char *key,
				  size_t len,
				  settings_read_cb read_cb,
				  void            *cb_arg,
				  void            *param)
{
	uint8_t buffer[SETTINGS_MAX_VAL_LEN];
	ssize_t num_read_bytes = MIN(len, SETTINGS_MAX_VAL_LEN);
	struct settings_read_callback_params *params = param;

	/* Process only the exact match and ignore descendants of the searched name */
	if (settings_name_next(key, NULL) != 0) {
		return 0;
	}

	params->value_found = true;
	num_read_bytes = read_cb(cb_arg, buffer, num_read_bytes);

	if (num_read_bytes < 0) {
		shell_error(params->shell_ptr, "Failed to read value: %d", (int) num_read_bytes);
		return 0;
	}

	shell_hexdump(params->shell_ptr, buffer, num_read_bytes);

	if (len > SETTINGS_MAX_VAL_LEN) {
		shell_print(params->shell_ptr, "(The output has been truncated)");
	}

	return 0;
}

static int cmd_read(const struct shell *shell_ptr, size_t argc, char *argv[])
{
	int err;
	const char *name = argv[1];

	struct settings_read_callback_params params = {
		.shell_ptr = shell_ptr,
		.value_found = false
	};

	err = settings_load_subtree_direct(name, settings_read_callback, &params);

	if (err) {
		shell_error(shell_ptr, "Failed to load setting: %d", err);
	} else if (!params.value_found) {
		err = -ENOENT;
		shell_error(shell_ptr, "Setting not found");
	}

	return err;
}

static int cmd_write(const struct shell *shell_ptr, size_t argc, char *argv[])
{
	int err;
	uint8_t buffer[CONFIG_SHELL_CMD_BUFF_SIZE / 2];
	size_t buffer_len;

	buffer_len = hex2bin(argv[2], strlen(argv[2]), buffer, sizeof(buffer));

	if (buffer_len == 0) {
		shell_error(shell_ptr, "Failed to parse hex value");
		return -EINVAL;
	}

	err = settings_save_one(argv[1], buffer, buffer_len);

	if (err) {
		shell_error(shell_ptr, "Failed to write setting: %d", err);
	}

	return err;
}

static int cmd_delete(const struct shell *shell_ptr, size_t argc, char *argv[])
{
	int err;

	err = settings_delete(argv[1]);

	if (err) {
		shell_error(shell_ptr, "Failed to delete setting: %d", err);
	}

	return err;
}

SHELL_STATIC_SUBCMD_SET_CREATE(settings_cmds,
			       SHELL_CMD_ARG(list, NULL, "[<subtree>]", cmd_list, 1, 1),
			       SHELL_CMD_ARG(read, NULL, "<name>", cmd_read, 2, 0),
			       SHELL_CMD_ARG(write, NULL, "<name> <hex>", cmd_write, 3, 0),
			       SHELL_CMD_ARG(delete, NULL, "<name>", cmd_delete, 2, 0),
			       SHELL_SUBCMD_SET_END);

static int cmd_settings(const struct shell *shell_ptr, size_t argc, char **argv)
{
	shell_error(shell_ptr, "%s unknown parameter: %s", argv[0], argv[1]);
	return -EINVAL;
}

SHELL_CMD_ARG_REGISTER(settings, &settings_cmds, "Settings shell commands",
		       cmd_settings, 2, 0);
