/*
 * Copyright (c) 2018 Nordic Semiconductor ASA
 * Copyright (c) 2015 Runtime Inc
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <string.h>
#include <stdio.h>

#include <zephyr/types.h>
#include <stddef.h>
#include <sys/types.h>
#include <errno.h>

#include "settings/settings.h"
#include "settings_priv.h"

#include <logging/log.h>
LOG_MODULE_DECLARE(settings, CONFIG_SETTINGS_LOG_LEVEL);

struct settings_dup_check_arg {
	const char *name;
	const char *val;
	size_t val_len;
	int is_dup;
};

sys_slist_t  settings_load_srcs;
struct settings_store *settings_save_dst;

void settings_src_register(struct settings_store *cs)
{
	sys_snode_t *prev, *cur;

	prev = NULL;

	SYS_SLIST_FOR_EACH_NODE(&settings_load_srcs, cur) {
		prev = cur;
	}

	sys_slist_insert(&settings_load_srcs, prev, &cs->cs_next);
}

void settings_dst_register(struct settings_store *cs)
{
	settings_save_dst = cs;
}

static void settings_load_cb(char *name, void *val_read_cb_ctx, off_t off,
			     void *cb_arg)
{
	int rc = settings_set_value_priv(name, val_read_cb_ctx, off, 0);

	if (rc != 0) {
		LOG_ERR("set-value failure. key: %s error(%d)",
			log_strdup(name), rc);
	} else {
		LOG_DBG("set-value OK. key: %s",
			log_strdup(name));
	}
	(void)rc;
}

int settings_load(void)
{
	struct settings_store *cs;

	/*
	 * for every config store
	 *    load config
	 *    apply config
	 *    commit all
	 */

	SYS_SLIST_FOR_EACH_CONTAINER(&settings_load_srcs, cs, cs_next) {
		cs->cs_itf->csi_load(cs, settings_load_cb, NULL);
	}
	return settings_commit(NULL);
}

/* val_off - offset of value-string within line entries */
static int settings_cmp(char const *val, size_t val_len, void *val_read_cb_ctx,
		 off_t val_off)
{
	size_t len_read, exp_len;
	size_t rem;
	char buf[16];
	int rc = -EINVAL;
	off_t off = 0;

	for (rem = val_len; rem > 0; rem -= len_read) {
		len_read = exp_len = MIN(sizeof(buf), rem);
		rc = settings_line_val_read(val_off, off, buf, len_read,
			   &len_read, val_read_cb_ctx);
		if (rc) {
			break;
		}

		if (len_read != exp_len) {
			rc = 1;
			break;
		}

		rc = memcmp(val, buf, len_read);
		if (rc) {
			break;
		}
		val += len_read;
		off += len_read;
	}

	return rc;
}

static void settings_dup_check_cb(char *name, void *val_read_cb_ctx, off_t off,
				  void *cb_arg)
{
	struct settings_dup_check_arg *cdca = (struct settings_dup_check_arg *)
					      cb_arg;
	size_t len_read;

	if (strcmp(name, cdca->name)) {
		return;
	}

	len_read = settings_line_val_get_len(off, val_read_cb_ctx);
	if (len_read != cdca->val_len) {
		cdca->is_dup = 0;
	} else if (len_read == 0) {
		cdca->is_dup = 1;
	} else {
		if (!settings_cmp(cdca->val, cdca->val_len,
				  val_read_cb_ctx, off)) {
			cdca->is_dup = 1;
		} else {
			cdca->is_dup = 0;
		}
	}
}

/*
 * Append a single value to persisted config. Don't store duplicate value.
 */
int settings_save_one(const char *name, void *value, size_t val_len)
{
	struct settings_store *cs;
	struct settings_dup_check_arg cdca;

	cs = settings_save_dst;
	if (!cs) {
		return -ENOENT;
	}

	if (val_len > 0 && value == NULL) {
		return -EINVAL;
	}

	/*
	 * Check if we're writing the same value again.
	 */
	cdca.name = name;
	cdca.val = (char *)value;
	cdca.is_dup = 0;
	cdca.val_len = val_len;
	cs->cs_itf->csi_load(cs, settings_dup_check_cb, &cdca);
	if (cdca.is_dup == 1) {
		return 0;
	}
	return cs->cs_itf->csi_save(cs, name, (char *)value, val_len);
}

int settings_delete(const char *name)
{
	return settings_save_one(name, NULL, 0);
}

int settings_save(void)
{
	struct settings_store *cs;
	struct settings_handler *ch;
	int rc;
	int rc2;

	cs = settings_save_dst;
	if (!cs) {
		return -ENOENT;
	}

	if (cs->cs_itf->csi_save_start) {
		cs->cs_itf->csi_save_start(cs);
	}
	rc = 0;

	SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) {
		if (ch->h_export) {
			rc2 = ch->h_export(settings_save_one);
			if (!rc) {
				rc = rc2;
			}
		}
	}
	if (cs->cs_itf->csi_save_end) {
		cs->cs_itf->csi_save_end(cs);
	}
	return rc;
}

void settings_store_init(void)
{
	sys_slist_init(&settings_load_srcs);
}
