#ifndef VENTILATIONCONTROL_H
#define VENTILATIONCONTROL_H

#include <Arduino.h>
#include <Wire.h>
#include "common.h"
#include "GenericPWM.h"
#include "SettingsManager.h"
#include "DHTAsyncSensors.h"
#include "FireWatch.h"
#include "WiderServoTimer2.h"

class VentilationControl {
private:
    WiderServoTimer2 fanDoorServo;
    byte servoPin;
    byte fanPWMPIN;
    byte fanRelayPIN;
    byte fanRPMPIN;
    const byte* doorPositions;
    byte numPositions;
    byte fanDuty;
    byte lastFanDuty;
    bool fanOn;
    float tempMaxInside;
    float tempMaxDiff;
    float prevTempDiff;
    unsigned long lastTempDiffUpdateTime;
    unsigned long lastFanDoorPositionUpdateTime;
    unsigned long fanRelayPowerOnTime;
    byte pulsesPerFanRevolution;
    word fanStuckTreshold;
    word fanDoorSpeed;
    word currentFanDoorServoPulse;
    GenericPWM* pwmController;
    FireWatch* fireWatch;

    // Fan RPM monitoring variables
    static VentilationControl* instance; // Static instance pointer for interrupt handling
    volatile unsigned long fanTS1 = 0;   // Timestamp of the last interrupt
    volatile unsigned long fanTS2 = 0;   // Timestamp of the current interrupt
    

    // Helper methods
    byte calculateFanDuty(float tempDiff, float convergenceRate);
    byte calculateDoorPosition(float tempDiff);
    void setFanSpeed(byte duty);
    void turnFanOn();
    void turnFanOff();

    void setFanDoorPosition(byte targetPos);

    static void fanRotationSensTriggered(); // Static interrupt handler

public:
    // Default door positions and temperature thresholds
    static const byte DEFAULT_DOOR_POSITIONS[];

    //default constants for fan RPM reading
    static constexpr byte DEBOUNCE = 0;             // Debounce time in ms
    static constexpr word DEFAULT_FANSTUCK_THRESHOLD = 500; // Threshold to detect a stuck fan in ms
    static constexpr byte DEFAULT_PULSES_PER_FAN_REVOLUTION = 2;    // Adjust for your fan

    static constexpr word PULSE_0_DEGREE = MIN_PULSE_WIDTH;
    static constexpr word PULSE_90_DEGREE = MIN_PULSE_WIDTH + ((MAX_PULSE_WIDTH - MIN_PULSE_WIDTH) / 2);
    static constexpr byte PULSE_WIDTH_PER_DEGREE = (byte)((PULSE_90_DEGREE - PULSE_0_DEGREE) / 90);

    // Constructors
    VentilationControl(byte servoPin, byte fanPWMPIN, byte fanRelayPIN, byte fanRPMPIN,
                       GenericPWM* pwmController,
					   FireWatch* fireWatch,
                       float tempMaxInside,
                       float tempMaxDiff,
                       const byte* doorPositions,                        
                       byte numPositions,
                       byte pulsesPerFanRevolution,
                       word fanStuckTreshold);
    VentilationControl(byte servoPin, byte fanPWMPIN, byte fanRelayPIN, byte fanRPMPIN, GenericPWM* pwmController, FireWatch* fireWatch);

    void attachServo();
    void attachFanInterrupt();
    void controlVentilation();
    bool isFanOn() const;
    word calcFANRPM();    

    float getMaxInsideTemp() const { return tempMaxInside; };
    float getMaxTempDifference() const { return tempMaxDiff; };
    void setMaxInsideTemp(float fTemp);
    void setMaxTempDifference(float fDiff);


    ~VentilationControl();
};

#endif
