/*
 * Copyright (c) 2019 Alexander Wachter
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/sys/printk.h>
#include <zephyr/shell/shell.h>
#include <zephyr/drivers/hwinfo.h>
#include <zephyr/types.h>
#include <zephyr/logging/log.h>

static int cmd_get_device_id(const struct shell *sh, size_t argc, char **argv)
{
	uint8_t dev_id[16];
	ssize_t length;
	int i;

	length = hwinfo_get_device_id(dev_id, sizeof(dev_id));

	if (length == -ENOSYS) {
		shell_error(sh, "Not supported by hardware");
		return -ENOSYS;
	} else if (length < 0) {
		shell_error(sh, "Error: %zd", length);
		return length;
	}

	shell_fprintf(sh, SHELL_NORMAL, "Length: %zd\n", length);
	shell_fprintf(sh, SHELL_NORMAL, "ID: 0x");

	for (i = 0 ; i < length ; i++) {
		shell_fprintf(sh, SHELL_NORMAL, "%02x", dev_id[i]);
	}

	shell_fprintf(sh, SHELL_NORMAL, "\n");

	return 0;
}

static int cmd_get_device_eui64(const struct shell *sh, size_t argc, char **argv)
{
	uint8_t dev_eui64[8];
	int ret;
	int i;

	ret = hwinfo_get_device_eui64(dev_eui64);

	if (ret == -ENOSYS) {
		shell_error(sh, "Not supported by hardware");
		return -ENOSYS;
	} else if (ret < 0) {
		shell_error(sh, "Error: %d", ret);
		return ret;
	}

	shell_fprintf(sh, SHELL_NORMAL, "EUI64: 0x");

	for (i = 0 ; i < 8 ; i++) {
		shell_fprintf(sh, SHELL_NORMAL, "%02x", dev_eui64[i]);
	}

	shell_fprintf(sh, SHELL_NORMAL, "\n");

	return 0;
}

static inline const char *cause_to_string(uint32_t cause)
{
	switch (cause) {
	case RESET_PIN:
		return "pin";

	case RESET_SOFTWARE:
		return "software";

	case RESET_BROWNOUT:
		return "brownout";

	case RESET_POR:
		return "power-on reset";

	case RESET_WATCHDOG:
		return "watchdog";

	case RESET_DEBUG:
		return "debug";

	case RESET_SECURITY:
		return "security";

	case RESET_LOW_POWER_WAKE:
		return "low power wake-up";

	case RESET_CPU_LOCKUP:
		return "CPU lockup";

	case RESET_PARITY:
		return "parity error";

	case RESET_PLL:
		return "PLL error";

	case RESET_CLOCK:
		return "clock";

	case RESET_HARDWARE:
		return "hardware";

	case RESET_USER:
		return "user";

	case RESET_TEMPERATURE:
		return "temperature";

	default:
		return "unknown";
	}
}

static void print_all_reset_causes(const struct shell *sh, uint32_t cause)
{
	for (uint32_t cause_mask = 1; cause_mask; cause_mask <<= 1) {
		if (cause & cause_mask) {
			shell_print(sh, "- %s",
				    cause_to_string(cause & cause_mask));
		}
	}
}

static int cmd_show_reset_cause(const struct shell *sh, size_t argc,
				char **argv)
{
	int res;
	uint32_t cause;

	ARG_UNUSED(argc);
	ARG_UNUSED(argv);

	res = hwinfo_get_reset_cause(&cause);
	if (res == -ENOSYS) {
		shell_error(sh, "Not supported by hardware");
		return res;
	} else if (res != 0) {
		shell_error(sh, "Error reading the cause [%d]", res);
		return res;
	}

	if (cause != 0) {
		shell_print(sh, "reset caused by:");
		print_all_reset_causes(sh, cause);
	} else {
		shell_print(sh, "No reset cause set");
	}

	return 0;
}

static int cmd_clear_reset_cause(const struct shell *sh, size_t argc,
				 char **argv)
{
	int res;

	ARG_UNUSED(argc);
	ARG_UNUSED(argv);

	res = hwinfo_clear_reset_cause();
	if (res == -ENOSYS) {
		shell_error(sh, "Not supported by hardware");
	} else if (res != 0) {
		shell_error(sh, "Error clearing the reset causes [%d]", res);
		return res;
	}

	return 0;
}

static int cmd_supported_reset_cause(const struct shell *sh, size_t argc,
				     char **argv)
{
	uint32_t cause;
	int res;

	ARG_UNUSED(argc);
	ARG_UNUSED(argv);

	res = hwinfo_get_supported_reset_cause(&cause);
	if (res == -ENOSYS) {
		shell_error(sh, "Not supported by hardware");
	} else if (res != 0) {
		shell_error(sh, "Could not get the supported reset causes [%d]", res);
		return res;
	}

	if (cause != 0) {
		shell_print(sh, "supported reset causes:");
		print_all_reset_causes(sh, cause);
	} else {
		shell_print(sh, "No causes supported");
	}

	return 0;
}

SHELL_STATIC_SUBCMD_SET_CREATE(sub_reset_cause,
	SHELL_CMD_ARG(show, NULL, "Show persistent reset causes",
		      cmd_show_reset_cause, 1, 0),
	SHELL_CMD_ARG(clear, NULL, "Clear all persistent reset causes",
		      cmd_clear_reset_cause, 1, 0),
	SHELL_CMD_ARG(supported, NULL,
		      "Get a list of all supported reset causes",
		      cmd_supported_reset_cause, 1, 0),
	SHELL_SUBCMD_SET_END /* Array terminated. */
);

SHELL_STATIC_SUBCMD_SET_CREATE(sub_hwinfo,
	SHELL_CMD_ARG(devid, NULL, "Show device id", cmd_get_device_id, 1, 0),
	SHELL_CMD_ARG(deveui64, NULL, "Show device eui64", cmd_get_device_eui64, 1, 0),
	SHELL_CMD_ARG(reset_cause, &sub_reset_cause, "Reset cause commands",
		      cmd_show_reset_cause, 1, 0),
	SHELL_SUBCMD_SET_END /* Array terminated. */
);

SHELL_CMD_ARG_REGISTER(hwinfo, &sub_hwinfo, "HWINFO commands", NULL, 2, 0);
