// Define pin numbers for the LEDs
const int RED_PIN = 13;
const int GREEN_PIN = 12;
const int BLUE_PIN = 11;

// Define pin numbers for the buttons
const int COLOR_BTN_PIN = 6;
const int DURATION_BTN_PIN = 7;

// Color and duration settings
enum Color {
    WHITE, RED, GREEN, BLUE, CYAN, YELLOW, MAGENTA, COLOR_COUNT
};
Color currentColor = WHITE;

enum Duration {
    DURATION_1000MS, DURATION_800MS, DURATION_600MS, DURATION_400MS, DURATION_200MS, DURATION_COUNT
};
Duration currentDuration = DURATION_1000MS;

// Predefined colors
const byte colors[COLOR_COUNT][3] = {
    {255, 255, 255}, // White
    {255, 0, 0},     // Red
    {0, 255, 0},     // Green
    {0, 0, 255},     // Blue
    {0, 255, 255},   // Cyan
    {255, 255, 0},   // Yellow
    {255, 0, 255}    // Magenta
};

// Predefined durations in milliseconds
const unsigned long durations[DURATION_COUNT] = {
    1000, 800, 600, 400, 200
};

// Global variables
unsigned long lastBlinkTime = 0;
unsigned long blinkInterval = 1000;
bool ledState = false;

void setup() {
    // Initialize serial communication
    Serial.begin(9600);

    // Initialize LED pins as outputs
    pinMode(RED_PIN, OUTPUT);
    pinMode(GREEN_PIN, OUTPUT);
    pinMode(BLUE_PIN, OUTPUT);

    // Initialize button pins as inputs with pull-up resistors
    pinMode(COLOR_BTN_PIN, INPUT_PULLUP);
    pinMode(DURATION_BTN_PIN, INPUT_PULLUP);

    // Attach interrupts to buttons
    attachInterrupt(digitalPinToInterrupt(COLOR_BTN_PIN), changeColor, FALLING);
    attachInterrupt(digitalPinToInterrupt(DURATION_BTN_PIN), changeDuration, FALLING);

    // Set initial LED color and duration
    updateLED();
    lastBlinkTime = millis(); // Initialize the blink timer
}

void loop() {
    unsigned long currentMillis = millis();
    
    // Check if it's time to blink the LED
    if (currentMillis - lastBlinkTime >= blinkInterval) {
        lastBlinkTime = currentMillis;
        ledState = !ledState;
        updateLED();
    }
}

// Function to update the LED based on the current color
void updateLED() {
    byte r = colors[currentColor][0];
    byte g = colors[currentColor][1];
    byte b = colors[currentColor][2];

    analogWrite(RED_PIN, r);
    analogWrite(GREEN_PIN, g);
    analogWrite(BLUE_PIN, b);

    // Print current settings to the serial monitor
    Serial.print("Color: ");
    Serial.print(colorToString(currentColor));
    Serial.print(" | Duration: ");
    Serial.print(durations[currentDuration]);
    Serial.println(" ms");
}

// Function to convert color enum to string
const char* colorToString(Color color) {
    switch (color) {
        case WHITE: return "White";
        case RED: return "Red";
        case GREEN: return "Green";
        case BLUE: return "Blue";
        case CYAN: return "Cyan";
        case YELLOW: return "Yellow";
        case MAGENTA: return "Magenta";
        default: return "Unknown";
    }
}

// Interrupt Service Routine for color button
void changeColor() {
    // Debouncing
    delay(50);
    if (digitalRead(COLOR_BTN_PIN) == LOW) {
        currentColor = static_cast<Color>((currentColor + 1) % COLOR_COUNT);
        updateLED();
    }
}

// Interrupt Service Routine for duration button
void changeDuration() {
    // Debouncing
    delay(50);
    if (digitalRead(DURATION_BTN_PIN) == LOW) {
        currentDuration = static_cast<Duration>((currentDuration + 1) % DURATION_COUNT);
        blinkInterval = durations[currentDuration];
        updateLED();
    }
}