#ifndef SETTINGSMANAGER_H
#define SETTINGSMANAGER_H

#include <Arduino.h>
#include <RotaryEncoder.h>
#include <EEPROM.h>
#include "common.h"
#include "LCDHelper.h"

/**
 *
 * TODO: Add variable for threshold PPM
 */
class SettingsManager {
private:
    RotaryEncoder* encoder;
    LCDHelper* lcdHelper;
    byte buttonPin;
    unsigned long lastInteractionTime;
    static const word INACTIVITY_TIMEOUT = 10000; // 10 seconds

    // Updated Modes
    enum Mode { SETUP_OFF, VARIABLE_DISPLAY, VARIABLE_SETUP } mode;
    byte currentVariableIndex;
    byte currentVariableEditValue;		//the value of variable that is currently being edited
    bool lastButtonState;
    bool buttonPressed;

    long lastEncodePos;
    unsigned long lastButtonDebounceTime; 	// Stores last button press time
    word buttonDebounceDelay;				//button debounce delay

    // Variables to manage with default values
    byte variables[18] = {
        AUTO_MODE, // bTempControlMode
        DEFAULT_TEMP_MAX_INSIDE,        // min temp difference
		DEFAULT_TEMP_MAX_DIFF,  //max temp difference
		DEFAULT_WARNING_TEMP,        // bWarningTemp
		DEFAULT_SHUTDOWN_TEMP,        // bShutdownTemp
		DEFAULT_ALARM_PPM / MULTIPLIER_100,	//alarm PPM
		DEFAULT_SHUTDOWN_PPM / MULTIPLIER_100,		//shutdown PPM
		MIN_FAN_DOOR_ANGLE,         // bFanDoorAngle
		FAN_DOOR_SPEED / MULTIPLIER_10, //fan door speed
        FAN_OFF_DUTY,   // bFanPWM
		LIGHT_LED_OFF, //led light off
        0,         // bLEDPWM
        static_cast<byte>(FireAlertMode::NORMAL),  // fire not detected
		DEFAULT_GAS_SENSE_WARMUP_TIME / MULTIPLIER_1000 / MULTIPLIER_10,  //gas sensor warmup time in tenths of seconds, 1=10s
		PWR_RELAY_OVERRIDE_ON,
		WDT_OFF,			//disable DWT by default
		DEFAULT_INFO_DISPLAY_SPEED,
		MIN_FAN_DOOR_ANGLE		//last fan door position
    };

    // EEPROM addresses
    static constexpr byte EEPROM_MAGIC_NUM_ADDRESS = 0;
    static constexpr byte EEPROM_BASE_ADDRESS = 1;
    static constexpr byte MAGIC_NUMBER = 0x87;
    static const byte NUM_VARIABLES;						//total number of variables
    static const byte NUM_SETUP_VARIABLES;			//how many variables can be setup
    static constexpr byte DEFAULT_DEBOUNCE_DELAY = 200;

    // Helper methods
    void loadFromEEPROM();
    void saveToEEPROM();
    void enterVariableDisplayMode();
    void enterVariableSetupMode();
    void updateVariableValue();
    void exitToSetupOff();
    void displayCurrentVariable();
    void saveVariableToEEPROM(byte index, byte value);
    byte readVariableFromEEPROM(byte index);
    void checkButton();
    
    // Value range checks
    byte constrainValue(byte value, byte min, byte max);
    byte constrainAngleValue(byte value);

    void (*onVariableChangedCallback)(byte variable, byte newValue);  // Function pointer for the callback

public:
    // Constants for Control Modes
	static constexpr byte AUTO_MODE = 0;
	static constexpr byte MANUAL_MODE = 1;

	static constexpr byte FAN_DOOR_ANGLE_AUTO = 255;

	//constanst for managed variables
	static constexpr byte VAR_TEMP_CONTROL_MODE = 0;
	static constexpr byte VAR_MAX_TEMP_INSIDE = 1;
	static constexpr byte VAR_MAX_TEMP_DIFFERENCE = 2;
	static constexpr byte VAR_WARNING_TEMP = 3;
	static constexpr byte VAR_SHUTDOWN_TEMP = 4;
	static constexpr byte VAR_ALERT_PPM = 5;
	static constexpr byte VAR_SHUTDOWN_PPM = 6;
	static constexpr byte VAR_FAN_DOOR_ANGLE = 7;
	static constexpr byte VAR_FAN_DOOR_SPEED = 8;
	static constexpr byte VAR_FAN_PWM = 9;
	static constexpr byte VAR_LED_ON = 10;
	static constexpr byte VAR_LED_PWM = 11;
	static constexpr byte VAR_FIRE_ALERT_MODE = 12;
	static constexpr byte VAR_GASSENS_WARMUP_TIME = 13;
	static constexpr byte VAR_PWR_RELAY_OVERRIDE = 14;			//power relay override allowing to force power ON
	static constexpr byte VAR_ENABLE_WDT = 15;					//whether to enable watch dog time
	static constexpr byte VAR_INFO_DISPLAY_SPEED = 16;
	static constexpr byte VAR_LAST_FAN_DOOR_POSITION = 17;

    // Constructor
    SettingsManager(RotaryEncoder* encoder, LCDHelper* lcdHelper, byte buttonPin);

    void init();
    // Main loop to be called in the Arduino loop
    void handleEncoderInput();

    //getters
    byte getTempControlMode() const;
    byte getMaxInsideTemp() const;
    byte getMaxTempDifference() const;
    byte getWarningTemp() const;
    byte getShutdownTemp() const;
    word getAlertPPM() const;
    word getShutdownPPM() const;
    byte getFanDoorAngle() const;
    word getFanDoorSpeed() const;
    byte getFanPWM() const;
    byte getLEDOn() const;
    byte getLEDPWM() const;
    FireAlertMode getFireAlertMode() const;
    unsigned long getGasSensWarmupTime() const;
    byte getPowerRelayOverride() const;
    byte getEnableWDT() const;
    byte getInfoDisplaySpeed() const;
    byte getLastFanDoorPosition() const;

    void setFireAlertMode(FireAlertMode alertMode);
    void setLastFanDoorPosition(byte doorPosition);

    void onVariableChanged(void (*callback)(byte variable, byte newValue));		//to set callback

    // Check if in SETUP_OFF mode
    bool isSetupOff() const;
};

#endif
