/*
 * debug.h - debug and logging header file
 *
 * Copyright (C) 2019-2025 IOPSYS Software Solutions AB. All rights reserved.
 *
 * Author: anjan.chanda@iopsys.eu
 *
 */

#ifndef DEBUG_H
#define DEBUG_H

#include <stdint.h>
#include <stdbool.h>

uint32_t logfeature_to_enum(const char *s);
const char *logfeature_to_string(uint32_t e);
void restart_logging(void *args);
void stop_logging(void);
void log_message(int feature, int level, const char *fmt, ...)
#ifdef __GNUC__
	__attribute__((__format__(__printf__, 3, 4)));
#endif
void log_test(int level, void *var, int len);
void log_cmdu(int level, void *var);

#define DEBUG_COLOR	1

/* log feature categories */
enum {
	LOG_TIMER,	/* Timers */
	LOG_STEER,	/* STA steering */
	LOG_BSTEER,	/* BSTA steering */
	LOG_APCFG,	/* AP Autoconfiguration */
	LOG_STA,	/* STA info */
	LOG_DPP,	/* DPP */
	LOG_DCNTLR,	/* Dynamic Controller */
	LOG_TS,		/* L2 Traffic Separation */
	LOG_QOS,	/* QoS and Service Prioritization */
	LOG_MISC,	/* Misc logs to aid debugging */
	LOG_CHANNEL,	/* Channel preferences */
	LOG_SCAN,	/* Channel scanning */
#if (EASYMESH_VERSION >= 6)
	LOG_MLO,	/* MLO logging */
#endif
#ifdef DYNBH
	LOG_DYNBH,	/* Dynamic Ethernet backhaul management */
#endif
	LOG_DEFAULT,	/* uncategorized messages */
};

/* log levels */
enum {
	LOGLEVEL_UNSET = -1,
	LOGLEVEL_ERROR,
	LOGLEVEL_WARN,
	LOGLEVEL_INFO,
	LOGLEVEL_DEBUG,
	LOGLEVEL_TRACE,
	LOGLEVEL_MAX = LOGLEVEL_TRACE,
};

#define LOG_FEATURE(x)	BIT(x)
#define LOG_FEATURE_ALL	(BIT(LOG_DEFAULT) | (BIT(LOG_DEFAULT) - 1))

#define DEFAULT_LOGLEVEL	LOGLEVEL_INFO

struct log_options {
	uint32_t features;
	int level;
	const char *logfile;
	bool logfile_isfifo;
	bool syslogging;
};


#ifdef DEBUG_COLOR

#define red             "\033[0;31m"
#define green           "\033[0;32m"
#define yellow          "\033[1;33m"
#define brown           "\033[0;33m"
#define blue            "\033[0;34m"
#define magenta         "\033[0;35m"
#define bgred           "\033[48;5;196m"
#define bggreen         "\033[48;5;046m"
#define bgyellow        "\033[48;5;226m"
#define bgblue          "\033[48;5;037m"
#define nocl            "\033[0m"

#define err(fmt, ...)         log_message(LOG_DEFAULT, 0, red fmt nocl, ## __VA_ARGS__)
#define warn(fmt, ...)        log_message(LOG_DEFAULT, 1, red fmt nocl, ## __VA_ARGS__)
#define info(fmt, ...)        log_message(LOG_DEFAULT, 2, blue fmt nocl, ## __VA_ARGS__)
#define dbg(fmt, ...)         log_message(LOG_DEFAULT, 3, nocl fmt nocl, ## __VA_ARGS__)
#define trace(fmt, ...)       log_message(LOG_DEFAULT, 4, fmt, ## __VA_ARGS__)
#define trace_cmd(fmt, ...)   log_message(LOG_DEFAULT, 4, brown fmt nocl, ## __VA_ARGS__)
#define loud(fmt, ...)        log_message(LOG_DEFAULT, 5, fmt, ## __VA_ARGS__)

#else /* DEBUG_COLOR */

#define err(...)	          log_message(LOG_DEFAULT, 0, __VA_ARGS__)
#define warn(...)	          log_message(LOG_DEFAULT, 1, __VA_ARGS__)
#define info(...)	          log_message(LOG_DEFAULT, 2, __VA_ARGS__)
#define dbg(...)	          log_message(LOG_DEFAULT, 3, __VA_ARGS__)
#define trace(...)	          log_message(LOG_DEFAULT, 4, __VA_ARGS__)
#define trace_cmd(...)	      log_message(LOG_DEFAULT, 4, __VA_ARGS__)
#define loud(...)	          log_message(LOG_DEFAULT, 5, __VA_ARGS__)

#endif /* DEBUG_COLOR */

#define agnt_err(feat, fmt, ...)         log_message(feat, 0, fmt, ## __VA_ARGS__)
#define agnt_warn(feat, fmt, ...)        log_message(feat, 1, fmt, ## __VA_ARGS__)
#define agnt_info(feat, fmt, ...)        log_message(feat, 2, fmt, ## __VA_ARGS__)
#define agnt_dbg(feat, fmt, ...)         log_message(feat, 3, fmt, ## __VA_ARGS__)
#define agnt_trace(feat, fmt, ...)       log_message(feat, 4, fmt, ## __VA_ARGS__)


#ifdef WARN_ON
#undef WARN_ON

#endif /* DEBUG_COLOR */

#define WARN_ON(cond) \
({ \
	typeof(cond) __c = (cond); \
	if (__c) \
		err("%sL%d@%s: [%s] failed\n", __FILE__, __LINE__, __func__, #cond); \
	__c; \
})

void dump(const unsigned char *buf, int len, char *label);

#endif /* DEBUG_H */
