#include <Arduino.h>
// === Pin Definitions ===
#define POT_BRIGHTNESS A0
#define POT_RGB_RED A2
#define POT_RGB_GREEN A3
#define POT_RGB_BLUE A4
#define LED_RED 13
#define LED_GREEN 12
#define LED_BLUE 5    // Hardware PWM pin
#define RGB_RED 11
#define RGB_GREEN 10
#define RGB_BLUE 9
#define BTN_RED 8
#define BTN_GREEN 7
#define BTN_BLUE 6
#define BTN_RESET 2
// === State Variables ===
bool blinking[3] = {true, true, true};
bool ledState[3] = {false, false, false};
bool buttonEnabled[3] = {true, true, true};
unsigned long lastBlinkMillis = 0;
const unsigned long blinkInterval = 2000;
// Debounce handling
unsigned long lastDebounceTime[3] = {0, 0, 0};
const unsigned long debounceDelay = 50;
int lastButtonState[3] = {HIGH, HIGH, HIGH};
void resetSystem();
// === Setup function ===
void setup() {
  Serial.begin(9600);
  pinMode(LED_RED, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);
  pinMode(RGB_RED, OUTPUT);
  pinMode(RGB_GREEN, OUTPUT);
  pinMode(RGB_BLUE, OUTPUT);
  pinMode(BTN_RED, INPUT_PULLUP);
  pinMode(BTN_GREEN, INPUT_PULLUP);
  pinMode(BTN_BLUE, INPUT_PULLUP);
  pinMode(BTN_RESET, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(BTN_RESET), resetSystem, FALLING);
  Serial.println("System Initialized");
}
// === Main loop ===
void loop() {
  handleBlinking();
  handleButtons();
  handleRGB();
  handleBlueLEDBrightness();
  handleSerial();
}
// === Blink all LEDs together every 2 sec ===
void handleBlinking() {
  unsigned long currentMillis = millis();
  if (currentMillis - lastBlinkMillis >= blinkInterval) {
    lastBlinkMillis = currentMillis;
    for (int i = 0; i < 3; i++) {
      if (blinking[i]) {
        ledState[i] = !ledState[i];
        digitalWrite(getLEDPin(i), ledState[i]);
      }
    }
  }
}
// === Buttons Handling with debounce ===
void handleButtons() {
  checkButton(BTN_RED, 0);
  checkButton(BTN_GREEN, 1);
  checkButton(BTN_BLUE, 2);
}
// Button debouncing
void checkButton(int buttonPin, int ledIndex) {
  static unsigned long lastDebounceTime[3] = {0, 0, 0};
  static int lastStableState[3] = {HIGH, HIGH, HIGH};
  static int buttonState[3] = {HIGH, HIGH, HIGH};
  int currentReading = digitalRead(buttonPin);
  if (currentReading != buttonState[ledIndex]) {
    lastDebounceTime[ledIndex] = millis();
    buttonState[ledIndex] = currentReading;
  }
  if ((millis() - lastDebounceTime[ledIndex]) > 50) { // Debounce delay of 50ms
    if (buttonState[ledIndex] == LOW && lastStableState[ledIndex] == HIGH && buttonEnabled[ledIndex]) {
      blinking[ledIndex] = false;
      ledState[ledIndex] = !ledState[ledIndex];
      digitalWrite(getLEDPin(ledIndex), ledState[ledIndex]);
      
      Serial.print("LED ");
      Serial.print(ledIndex + 1);
      Serial.println(ledState[ledIndex] ? " ON" : " OFF");
    }
    lastStableState[ledIndex] = buttonState[ledIndex];
  }
}
// === Hardware PWM for Blue LED brightness ===
void handleBlueLEDBrightness() {
  int brightness = map(analogRead(POT_BRIGHTNESS), 0, 1023, 0, 255);
  if (!blinking[2]) {
    analogWrite(LED_BLUE, ledState[2] ? brightness : 0);
  } else {
    analogWrite(LED_BLUE, ledState[2] ? brightness : 0);
  }
}
// === RGB LED Color Control ===
// === Corrected RGB LED Color Control for Common-Anode LED ===
void handleRGB() {
  // Read potentiometer values (0-1023)
  int redValue = analogRead(POT_RGB_RED);
  int greenValue = analogRead(POT_RGB_GREEN);
  int blueValue = analogRead(POT_RGB_BLUE);
  // Map potentiometer values to PWM (0-255) and invert for Common-Anode
  redValue = map(redValue, 0, 1023, 0, 255);
  greenValue = map(greenValue, 0, 1023, 0, 255);
  blueValue = map(blueValue, 0, 1023, 0, 255);
  // Output corrected inverted PWM signals
  analogWrite(RGB_RED, redValue);
  analogWrite(RGB_GREEN, greenValue);
  analogWrite(RGB_BLUE, blueValue);
}
// === Serial Commands Handler ===
void handleSerial() {
  if (Serial.available() > 0) {
    String input = Serial.readStringUntil('\n');
    input.trim();
    Serial.print("> ");
    Serial.println(input);
    // RED LED toggle
    if (input.equalsIgnoreCase("R")) {
      blinking[0] = false;
      ledState[0] = !ledState[0];
      digitalWrite(LED_RED, ledState[0]);
      Serial.print("Red LED is now ");
      Serial.println(ledState[0] ? "ON" : "OFF");
    }
    // GREEN LED toggle
    else if (input.equalsIgnoreCase("G")) {
      blinking[1] = false;
      ledState[1] = !ledState[1];
      digitalWrite(LED_GREEN, ledState[1]);
      Serial.print("Green LED is now ");
      Serial.println(ledState[1] ? "ON" : "OFF");
    }
    // BLUE LED brightness or toggle
    else if (input.startsWith("B")) {
      blinking[2] = false; // stop blinking on manual control
      input.remove(0,1);  // remove 'B' character
      input.trim();
      if (input.length() == 0) { // just "B" toggles LED on/off
        ledState[2] = !ledState[2];
        analogWrite(LED_BLUE, ledState[2] ? 255 : 0);
        Serial.print("Blue LED toggled ");
        Serial.println(ledState[2] ? "ON (Max brightness)" : "OFF");
      } else { // "B value" sets brightness
        int brightness = input.toInt();
        brightness = constrain(brightness, 0, 255);
        analogWrite(LED_BLUE, brightness);
        Serial.print("Blue LED brightness set to: ");
        Serial.println(brightness);
      }
    }
    // RGB ON (all LEDs active based on potentiometer)
    else if (input.equalsIgnoreCase("RGB on")) {
      Serial.println("RGB LED control activated (potentiometers)");
      // You may add extra logic here if needed
    }
    // RGB OFF (turn off RGB completely)
    else if (input.equalsIgnoreCase("RGB off")) {
      analogWrite(RGB_RED, 255);
      analogWrite(RGB_GREEN, 255);
      analogWrite(RGB_BLUE, 255);
      Serial.println("RGB LED turned off");
    }
    else if (input.equalsIgnoreCase("disable button 1")) {
      buttonEnabled[0] = false;
      Serial.println("Button 1 disabled");
    }
    else if (input.equalsIgnoreCase("enable button 1")) {
      buttonEnabled[0] = true;
      Serial.println("Button 1 enabled");
    }
    else if (input.equalsIgnoreCase("disable button 2")) {
      buttonEnabled[1] = false;
      Serial.println("Button 2 disabled");
    }
    else if (input.equalsIgnoreCase("enable button 2")) {
      buttonEnabled[1] = true;
      Serial.println("Button 2 enabled");
    }
    else if (input.equalsIgnoreCase("disable button 3")) {
      buttonEnabled[2] = false;
      Serial.println("Button 3 disabled");
    }
    else if (input.equalsIgnoreCase("enable button 3")) {
      buttonEnabled[2] = true;
      Serial.println("Button 3 enabled");
    }
    else {
      Serial.println("Invalid command!");
    }
  }
}
// === Interrupt-based Reset ===
void resetSystem() {
  for (int i = 0; i < 3; i++) {
    blinking[i] = true;
    buttonEnabled[i] = true;
    ledState[i] = false;
    digitalWrite(getLEDPin(i), LOW);
  }
  Serial.println("System Reset!");
}
// === Helper function ===
int getLEDPin(int index) {
  switch (index) {
    case 0: return LED_RED;
    case 1: return LED_GREEN;
    case 2: return LED_BLUE;
  }
  return -1;
}