#ifndef GLOBALCONSTANTS_H
#define GLOBALCONSTANTS_H

constexpr byte FAN_IDLE_DUTY = 20;   // Minimum duty cycle for idle fan speed
constexpr byte FAN_OFF_DUTY = 0;    // Duty cycle for the fan to stop spinning
constexpr byte FAN_MAX_DUTY = 100;  // Maximum duty cycle for the fan

constexpr byte MULTIPLIER_10 = 10;
constexpr byte MULTIPLIER_100 = 100;
constexpr word MULTIPLIER_1000 = 1000;

constexpr byte MIN_TEMP_INSIDE = 5;
constexpr byte MIN_TEMP_DIFF = 1;
constexpr byte DEFAULT_TEMP_MAX_INSIDE = 30;
constexpr byte DEFAULT_TEMP_MAX_DIFF = 10;

constexpr byte INSIDE_SENSOR_MAX_TEMP = 80;
constexpr byte OUTSIDE_SENSOR_MAX_TEMP = 60;

constexpr byte DEFAULT_WARNING_TEMP = 60;
constexpr byte DEFAULT_SHUTDOWN_TEMP = 80;
constexpr byte DEFAULT_INFO_DISPLAY_SPEED = 5;
constexpr word DEFAULT_INFO_PAGE_DISPLAY_TIME = DEFAULT_INFO_DISPLAY_SPEED * MULTIPLIER_1000;   //the time in millis to display one info page

constexpr word LED_ON_DELAY = 5000;				//delay after startup when to first turn on LED stripe
constexpr word FAN_ON_DELAY = 8000; 			//delay after startup when to first allow switch FA relay ON

constexpr byte LCD_STRING_MAX_LEN = 32;  //for 1602 LCD

constexpr byte MIN_FAN_DOOR_ANGLE = 0;
constexpr byte MAX_FAN_DOOR_ANGLE = 90;
constexpr word FAN_DOOR_SPEED = 50;  //1 degree per 500 ms
constexpr byte MIN_FAN_DOOR_SPEED = 0;

constexpr word FIRE_ALARM_SIREN_MIN_FREQUENCY = 400;
constexpr word FIRE_ALARM_SIREN_MAX_FREQUENCY = 1000;
constexpr word FIRE_ALARM_SIREN_CYCLE_TIME = 2000;
constexpr byte FIRE_ALARM_SIREN_DELAY = 20;

constexpr word WARNING_SIREN_FREQUENCY = 800;
constexpr word WARNING_SIREN_BEEP_DURATION = 200;
constexpr word WARNING_SIREN_PAUSE_DURATION = 300;

//Definition of threshold values for fire hazard detection
constexpr word MIN_DETECT_PPM = 300;
constexpr word DEFAULT_ALARM_PPM = 500;
constexpr word DEFAULT_SHUTDOWN_PPM = 1000;

constexpr byte BYTE_MAX_VALUE = 255;

constexpr byte LIGHT_LED_ON = 1;
constexpr byte LIGHT_LED_OFF = 0;

constexpr byte PWR_RELAY_OVERRIDE_ON = 1;
constexpr byte PWR_RELAY_OVERRIDE_OFF = 0;

constexpr byte WDT_ON = 1;
constexpr byte WDT_OFF = 0;

constexpr unsigned long DEFAULT_GAS_SENSE_WARMUP_TIME = 180000;  // warm up time for gas sensor
constexpr byte MIN_GAS_SENSE_WARMUP_TIME = 2;			//2 for 20 seconds

#define STR_YES "Yes"
#define STR_NO "No"
#define STR_AUTO "Auto"
#define STR_MANUAL "Manual"
#define STR_ON "On"
#define STR_OFF "Off"

extern const char SM_STR_TEMP_CTRL_MODE[] PROGMEM;
extern const char SM_STR_MAX_TEMP_INSIDE[] PROGMEM;
extern const char SM_STR_MAX_TEMP_DIFF[] PROGMEM;
extern const char SM_STR_WARNING_TEMP[] PROGMEM;
extern const char SM_STR_SHUTDOWN_TEMP[] PROGMEM;
extern const char SM_STR_ALERT_PPM[] PROGMEM;
extern const char SM_STR_SHUTDOWN_PPM[] PROGMEM;
extern const char SM_STR_FAN_DOOR_ANGLE[] PROGMEM;
extern const char SM_STR_FAN_DOOR_SPEED[] PROGMEM;
extern const char SM_STR_FAN_PWM_OUT[] PROGMEM;
extern const char SM_STR_LED_ON[] PROGMEM;
extern const char SM_STR_LED_PWM_OUT[] PROGMEM;
extern const char SM_STR_FIRE_ALERT_MODE[] PROGMEM;
extern const char SM_STR_GAS_SENSE_WARMUP_TIME[] PROGMEM;
extern const char SM_STR_ENABLE_WDT[] PROGMEM;
extern const char SM_STR_INFO_DISPLAY_SPEED[] PROGMEM;
extern const char SM_STR_PWR_RELAY_OVERRIDE[] PROGMEM;

extern const char SM_STR_INVALID_VAR_INDEX[] PROGMEM;

extern const char SM_STR_FAM_NORMAL[] PROGMEM;
extern const char SM_STR_FAM_WARNING[] PROGMEM;
extern const char SM_STR_FAM_HAZARD[] PROGMEM;

extern const char SM_STR_INVALID[] PROGMEM;


#define SM_STR_EDIT "Set: "

#define STR_TEMP "T="
#define STR_WARN "WARN:"
#define STR_HUM "H="
#define STR_UNIT_CELSIUS "C"
#define STR_UNIT_PPM "PPM"
#define STR_UNIT_KOHM "kOhm"
#define STR_UNIT_MSDEG "ms/dg"
#define STR_UNIT_DEG "deg"
#define STR_UNIT_PERCENT "%"
#define STR_UNIT_SECONDS "s"

#define STR_SFA "SFA"
#define STR_OVERRIDE "OVRD"
#define STR_CLOSED "Closed"

#define STR_STATE "State:"
#define STR_ANGLE "Angle: "

#define STR_FORMAT_DOUBLE_STR "%s%s"
#define STR_FORMAT_DOUBLE_STR_SPACED "%s %s"
#define STR_FORMAT_BYTE_WORD_VALUE "%s%s %s"
#define STR_FORMAT_PWR_RELAY_STATE "%s %s (%s)"

enum FireAlertMode : byte {
		NORMAL = 0,
		FIRE_WARNING = 1,
		FIRE_HAZARD = 2
	};

/**
 * This function ill load string stored in PROGMEM for usage with functions that require string stored in SRAM
 *
 */
char* _loadFlashString(const __FlashStringHelper* flashStr);


#define MK4SC_DEBUG  // Comment this line to disable debugging

#ifdef MK4SC_DEBUG
    #define DEBUG_PRINTER Serial /**< Define where debug output will be printed.**/

	#define DEBUG_BUFFER_SIZE 128  /**< Buffer size for the debug messages. */
    extern char debugBuffer[DEBUG_BUFFER_SIZE];  // Global buffer for all debug macros
    extern char debugFlashStrBuffer[DEBUG_BUFFER_SIZE];  //global buffer for loading debug message stored in PROGMEM

    void _loadDebugFlashString(const __FlashStringHelper* flashStr, char* buffer, size_t bufferSize);

    #define DEBUG_INIT(baud) DEBUG_PRINTER.begin(baud); while (!DEBUG_PRINTER)

    #define DEBUG_PRINT(fmt, ...) { \
        memset(debugBuffer, 0, sizeof(debugBuffer)); \
        int len = snprintf(debugBuffer, sizeof(debugBuffer), fmt, ##__VA_ARGS__); \
        debugBuffer[sizeof(debugBuffer) - 1] = '\0'; \
        if (len > 0 && len < sizeof(debugBuffer)) DEBUG_PRINTER.print(debugBuffer); \
    }

    #define DEBUG_PRINTLN(fmt, ...) { \
        memset(debugBuffer, 0, sizeof(debugBuffer)); \
        int len = snprintf(debugBuffer, sizeof(debugBuffer), fmt, ##__VA_ARGS__); \
        debugBuffer[sizeof(debugBuffer) - 1] = '\0'; \
        if (len > 0 && len < sizeof(debugBuffer)) DEBUG_PRINTER.println(debugBuffer); \
    }

    #define DEBUG_PRINT_F(fmt, ...) { \
        _loadDebugFlashString(fmt, debugFlashStrBuffer, DEBUG_BUFFER_SIZE); \
        DEBUG_PRINT(debugFlashStrBuffer, ##__VA_ARGS__); \
    }

    #define DEBUG_PRINTLN_F(fmt, ...) { \
        _loadDebugFlashString(fmt, debugFlashStrBuffer, DEBUG_BUFFER_SIZE); \
        DEBUG_PRINTLN(debugFlashStrBuffer, ##__VA_ARGS__); \
    }

    // Macro to check if the specified interval has passed
	#define DEBUG_TIME_ELAPSED(interval, lastTimeVar) (millis() - (lastTimeVar) >= (interval))

	// Macro to reset the interval time
	#define DEBUG_RESET_TIME(lastTimeVar) (lastTimeVar = millis())

#else
    #define DEBUG_INIT(baud)
    #define DEBUG_PRINT(fmt, ...)
    #define DEBUG_PRINTLN(fmt, ...)
    #define DEBUG_PRINT_F(fmt, ...)
    #define DEBUG_PRINTLN_F(fmt, ...)
	#define DEBUG_TIME_ELAPSED(interval, lastTimeVar) (false)
    #define DEBUG_RESET_TIME(lastTimeVar)
#endif


#endif
