/*
 * Copyright (c) 2019 Vestas Wind Systems A/S
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/settings/settings.h>

#include <CANopen.h>
#include <CO_Emergency.h>
#include <CO_SDO.h>

#include <canopennode.h>

#define LOG_LEVEL CONFIG_CANOPEN_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(canopen_storage);

/* 's', 'a', 'v', 'e' from LSB to MSB */
#define STORE_PARAM_MAGIC   0x65766173UL

/* 'l', 'o', 'a', 'd' from LSB to MSB */
#define RESTORE_PARAM_MAGIC 0x64616F6CUL

/* Variables for reporting errors through CANopen once the stack is up */
static int canopen_storage_rom_error;
static int canopen_storage_eeprom_error;

static CO_SDO_abortCode_t canopen_odf_1010(CO_ODF_arg_t *odf_arg)
{
	CO_EM_t *em = odf_arg->object;
	uint32_t value;
	int err;

	value = CO_getUint32(odf_arg->data);

	if (odf_arg->reading) {
		return CO_SDO_AB_NONE;
	}

	/* Preserve old value */
	memcpy(odf_arg->data, odf_arg->ODdataStorage, sizeof(uint32_t));

	if (odf_arg->subIndex != 1U) {
		return CO_SDO_AB_NONE;
	}

	if (value != STORE_PARAM_MAGIC) {
		return CO_SDO_AB_DATA_TRANSF;
	}

	err = canopen_storage_save(CANOPEN_STORAGE_ROM);
	if (err) {
		LOG_ERR("failed to save object dictionary ROM entries (err %d)",
			err);
		CO_errorReport(em, CO_EM_NON_VOLATILE_MEMORY, CO_EMC_HARDWARE,
			       err);
		return CO_SDO_AB_HW;
	} else {
		LOG_DBG("saved object dictionary ROM entries");
	}

	return CO_SDO_AB_NONE;
}

static CO_SDO_abortCode_t canopen_odf_1011(CO_ODF_arg_t *odf_arg)
{
	CO_EM_t *em = odf_arg->object;
	bool failed = false;
	uint32_t value;
	int err;

	value = CO_getUint32(odf_arg->data);

	if (odf_arg->reading) {
		return CO_SDO_AB_NONE;
	}

	/* Preserve old value */
	memcpy(odf_arg->data, odf_arg->ODdataStorage, sizeof(uint32_t));

	if (odf_arg->subIndex < 1U) {
		return CO_SDO_AB_NONE;
	}

	if (value != RESTORE_PARAM_MAGIC) {
		return CO_SDO_AB_DATA_TRANSF;
	}

	err = canopen_storage_erase(CANOPEN_STORAGE_ROM);
	if (err == -ENOENT) {
		LOG_DBG("no object dictionary ROM entries to delete");
	} else if (err) {
		LOG_ERR("failed to delete object dictionary ROM entries"
			" (err %d)", err);
		CO_errorReport(em, CO_EM_NON_VOLATILE_MEMORY, CO_EMC_HARDWARE,
			       err);
		failed = true;
	} else {
		LOG_DBG("deleted object dictionary ROM entries");
	}

#ifdef CONFIG_CANOPENNODE_STORAGE_HANDLER_ERASES_EEPROM
	err = canopen_storage_erase(CANOPEN_STORAGE_EEPROM);
	if (err == -ENOENT) {
		LOG_DBG("no object dictionary EEPROM entries to delete");
	} else if (err) {
		LOG_ERR("failed to delete object dictionary EEPROM entries"
			" (err %d)", err);
		CO_errorReport(em, CO_EM_NON_VOLATILE_MEMORY, CO_EMC_HARDWARE,
			       err);
		failed = true;
	} else {
		LOG_DBG("deleted object dictionary EEPROM entries");
	}
#endif

	if (failed) {
		return CO_SDO_AB_HW;
	}

	return CO_SDO_AB_NONE;
}

static int canopen_settings_set(const char *key, size_t len_rd,
				settings_read_cb read_cb, void *cb_arg)
{
	const char *next;
	int nlen;
	ssize_t len;

	nlen = settings_name_next(key, &next);

	if (!strncmp(key, "eeprom", nlen)) {
		struct sCO_OD_EEPROM eeprom;

		len = read_cb(cb_arg, &eeprom, sizeof(eeprom));
		if (len < 0) {
			LOG_ERR("failed to restore object dictionary EEPROM"
				" entries (err %d)", len);
			canopen_storage_eeprom_error = len;
		} else {
			if ((eeprom.FirstWord == CO_OD_FIRST_LAST_WORD) &&
			    (eeprom.LastWord == CO_OD_FIRST_LAST_WORD)) {
				memcpy(&CO_OD_EEPROM, &eeprom,
				       sizeof(CO_OD_EEPROM));
				LOG_DBG("restored object dictionary EEPROM"
					" entries");
			} else {
				LOG_WRN("object dictionary EEPROM entries"
					" signature mismatch, skipping"
					" restore");
			}
		}

		return 0;
	} else if (!strncmp(key, "rom", nlen)) {
		struct sCO_OD_ROM rom;

		len = read_cb(cb_arg, &rom, sizeof(rom));
		if (len < 0) {
			LOG_ERR("failed to restore object dictionary ROM"
				" entries (err %d)", len);
			canopen_storage_rom_error = len;
		} else {
			if ((rom.FirstWord == CO_OD_FIRST_LAST_WORD) &&
			    (rom.LastWord == CO_OD_FIRST_LAST_WORD)) {
				memcpy(&CO_OD_ROM, &rom, sizeof(CO_OD_ROM));
				LOG_DBG("restored object dictionary ROM"
					" entries");
			} else {
				LOG_WRN("object dictionary ROM entries"
					" signature mismatch, skipping"
					" restore");
			}
		}

		return 0;
	}

	return 0;
}

SETTINGS_STATIC_HANDLER_DEFINE(canopen, "canopen", NULL,
			       canopen_settings_set, NULL, NULL);

void canopen_storage_attach(CO_SDO_t *sdo, CO_EM_t *em)
{
	CO_OD_configure(sdo, OD_H1010_STORE_PARAM_FUNC, canopen_odf_1010,
			em, 0U, 0U);
	CO_OD_configure(sdo, OD_H1011_REST_PARAM_FUNC, canopen_odf_1011,
			em, 0U, 0U);

	if (canopen_storage_eeprom_error) {
		CO_errorReport(em, CO_EM_NON_VOLATILE_MEMORY, CO_EMC_HARDWARE,
			       canopen_storage_eeprom_error);
	}

	if (canopen_storage_rom_error) {
		CO_errorReport(em, CO_EM_NON_VOLATILE_MEMORY, CO_EMC_HARDWARE,
			       canopen_storage_rom_error);
	}
}

int canopen_storage_save(enum canopen_storage storage)
{
	int ret = 0;

	if (storage == CANOPEN_STORAGE_ROM) {
		ret = settings_save_one("canopen/rom", &CO_OD_ROM,
					sizeof(CO_OD_ROM));
	} else if (storage == CANOPEN_STORAGE_EEPROM) {
		ret = settings_save_one("canopen/eeprom", &CO_OD_EEPROM,
					sizeof(CO_OD_EEPROM));
	}

	return ret;
}

int canopen_storage_erase(enum canopen_storage storage)
{
	int ret = 0;

	if (storage == CANOPEN_STORAGE_ROM) {
		ret = settings_delete("canopen/rom");
	} else if (storage == CANOPEN_STORAGE_EEPROM) {
		ret = settings_delete("canopen/eeprom");
	}

	return ret;
}
