#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_AHTX0.h>
#include <Wire.h>
#include <FastLED.h>
Adafruit_AHTX0 aht;
// FastLED WS2815 setup
#define NUM_LEDS 4     // Number of WS2815 LEDs
#define LED_PIN 18     // Pin connected to the WS2815 data pin on NodeMCU
CRGB leds[NUM_LEDS];
// LED Strip class to control WS2815
class LEDStrip {
  private:
    int currentLED = 0;
    unsigned long previousMillisLED = 0;
    const long interval = 20; // Speed of the running dot
    // Function to turn off all LEDs
    void clearLEDs() {
      for (int i = 0; i < NUM_LEDS; i++) {
        leds[i] = CRGB::Black;
      }
      FastLED.show();
    }
  public:
    void setup() {
      FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS); // Initialize WS2815 strip
      FastLED.clear();   // Clear the LEDs at startup
      FastLED.show();
    }
    void setColorByTemperature(float temp) {
      if (temp <= 40) {
        setColor(CRGB::Green);
      } else if (temp > 40 && temp <= 60) {
        setColor(CRGB::Orange);
      } else {
        setColor(CRGB::Red);
      }
    }
    // Function to set all LEDs to a single color
    void setColor(CRGB color) {
      for (int i = 0; i < NUM_LEDS; i++) {
        leds[i] = color;
      }
      FastLED.show();
    }
    // Running dot effect
    void runningDot(bool isRightTurn, unsigned long currentMillis) {
      if (currentMillis - previousMillisLED >= interval) {
        previousMillisLED = currentMillis;
        clearLEDs(); // Clear all LEDs before setting the running dot
        if (isRightTurn) {
          // Running dot from left to right
          leds[currentLED] = CRGB::Orange;
          FastLED.show();
          currentLED++;
          if (currentLED >= NUM_LEDS) {
            currentLED = 0; // Reset to the first LED when the end is reached
          }
        } else {
          // Running dot from right to left
          leds[NUM_LEDS - 1 - currentLED] = CRGB::Orange;
          FastLED.show();
          currentLED++;
          if (currentLED >= NUM_LEDS) {
            currentLED = 0; // Reset to the last LED when the start is reached
          }
        }
      }
    }
};
/////////////TEMP_AHT10/////////////////////////
class AHT10 {
  public:
    bool setup() {
      if (!aht.begin()) {
        Serial.println("AHT10 sensor not found");
        return false;
      }
      Serial.println("AHT10 sensor initialized");
      return true;
    }
    sensors_event_t getTemperature() {
      sensors_event_t tempEvent, humidityEvent;
      aht.getEvent(&humidityEvent, &tempEvent);
      return tempEvent;
    }
    sensors_event_t getHumidity() {
      sensors_event_t tempEvent, humidityEvent;
      aht.getEvent(&humidityEvent, &tempEvent); 
      return humidityEvent;
    }
};
/////////////SPEAKER/////////////////////////
class Speaker {
  private:
    const int speakerPin = 19;
    const int clickFrequency = 250;
    const int clickDuration = 100;   
  public:
    void setup() {
      pinMode(speakerPin, OUTPUT);
    }
    void click() {
      tone(speakerPin, clickFrequency, clickDuration);
    }
};
class AsyncTurnSignal {
  private:
    const int leftTurnSwitch = 2;
    const int rightTurnSwitch = 15;
    const int leftTurnRelay = 25;
    const int rightTurnRelay = 26;
    const int leftDRL = 27;
    const int rightDRL = 14;
    bool leftTurnState = false;
    bool rightTurnState = false;
    unsigned long previousMillisTurn = 0;
    const long turnInterval = 450;
    Speaker speaker;
    AHT10 aht10;
    LEDStrip ledStrip;
    void updateTurnState() {
      leftTurnState = digitalRead(leftTurnSwitch) == LOW;
      rightTurnState = digitalRead(rightTurnSwitch) == LOW;
    }
  void blinkTurnSignals(unsigned long currentMillis) {
    if (currentMillis - previousMillisTurn >= turnInterval) {
      previousMillisTurn = currentMillis;
      if (leftTurnState) {
        digitalWrite(leftDRL, LOW);
        digitalWrite(rightDRL, LOW);
        digitalWrite(leftTurnRelay, !digitalRead(leftTurnRelay));
        digitalWrite(leftDRL, digitalRead(leftTurnRelay));
        speaker.click();
        
        // Run the dot from right to left for the left turn
        ledStrip.runningDot(false, currentMillis);
      } else if (rightTurnState) {
        digitalWrite(rightDRL, LOW);
        digitalWrite(leftDRL, LOW);
        digitalWrite(rightTurnRelay, !digitalRead(rightTurnRelay));
        digitalWrite(rightDRL, digitalRead(rightTurnRelay));
        speaker.click();
        
        // Run the dot from left to right for the right turn
        ledStrip.runningDot(true, currentMillis);
      } else {
        digitalWrite(leftTurnRelay, LOW);
        digitalWrite(rightTurnRelay, LOW);
        digitalWrite(leftDRL, HIGH);
        digitalWrite(rightDRL, HIGH);
        
        // Optionally, turn off the running dot effect when no turn signal is active
        ledStrip.setColor(CRGB::Black);
      }
    }
  }
  public:
    void setup() {
      pinMode(leftTurnSwitch, INPUT_PULLUP);
      pinMode(rightTurnSwitch, INPUT_PULLUP);
      pinMode(leftTurnRelay, OUTPUT);
      pinMode(rightTurnRelay, OUTPUT);
      pinMode(leftDRL, OUTPUT);
      pinMode(rightDRL, OUTPUT);
      digitalWrite(leftTurnRelay, LOW);
      digitalWrite(rightTurnRelay, LOW);
      digitalWrite(leftDRL, HIGH);
      digitalWrite(rightDRL, HIGH);
      aht10.setup();
      speaker.setup();
      ledStrip.setup();
    }
    void loop(unsigned long currentMillis) {
      updateTurnState();
      blinkTurnSignals(currentMillis);
      // Get temperature and set LED color based on temperature
      // sensors_event_t tempEvent = aht10.getTemperature();
      // ledStrip.setColorByTemperature(tempEvent.temperature);
    }
};
AsyncTurnSignal asyncTurnSignal;
void setup() {
  Serial.begin(115200);
  asyncTurnSignal.setup();
}
void loop() {
  unsigned long currentMillis = millis();
  asyncTurnSignal.loop(currentMillis);
}