#include <FastLED.h>
#include <EEPROM.h>

// Define the Arduino pins connected to the buttons
int Buttons[] = {2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, A0, A1, A2, A3, A4, A5};

// Arrays to keep track of LEDs that are active and need to fade out or change rainbow color
bool ledsActive[21];
bool ledsRBActive[21];

// Arrays to store the current intensity of each LED segment
byte fadeValues[21];
byte RGBValues[21];

// Keep track of when each LED was turned ON
unsigned long ledsActiveStartTime[21];

int mode = 0; // Current color mode (0: Red, 1: Blue, 2: Green)
bool clrstate[21];

#define NUM_LEDS 60   // Total number of LEDs on the strip
#define LEDS_PER_GROUP 3   // LEDs to fill with each color
#define DATA_PIN 12   // Arduino pin connected to the data input of the first WS2812B LED

CRGB leds[NUM_LEDS];  // Array to store the color of each LED

void setup() {
  // Set the button pins as inputs
  for (int x = 0; x < 18; x++) {
    pinMode(Buttons[x], INPUT);
  }

  mode = EEPROM.read(0);  // Load the state
  if (mode >= 9) mode = 0;

  // Initialize FastLED with the correct LED configuration
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.clear();
  FastLED.show();
}

void loop() {
  // Check for button press and update LED colors
  for (int x = 0; x < 18; x++) {
    if (digitalRead(Buttons[x])) {
      if (mode != 9) LightLED(x + 1); // Light up corresponding LEDs for the pressed button
      else {
        clrstate[x+1] = !clrstate[x+1];

        changeCLR(x+1);
      }

    }
  }

  // Check if analog inputs A6 and A7 are above the threshold (button pressed) and light up LEDs accordingly
  if (analogRead(A6) > 512) {
    if (mode != 9) LightLED(19); // Light up corresponding LEDs for the pressed button
    else {
      clrstate[19] = !clrstate[19];

      changeCLR(19);
    }
  }

  if (analogRead(A7) > 512) {
    if (mode != 9) LightLED(20); // Light up corresponding LEDs for the pressed button
    else {
      clrstate[20] = !clrstate[20];

      changeCLR(20);
    }
  }

  // Check if digital pin 1 is pressed and change color mode
  if (digitalRead(1) == true) {
    mode++;
    if (mode >= 10) mode = 0; // Wrap around the color modes

    FastLED.clear();

    if (mode == 9) {
      fill_solid( leds, NUM_LEDS, CRGB::Yellow);
      FastLED.show();
    }

    EEPROM.update(0, mode); // Save the state
    delay(300); // Add a delay to avoid multiple rapid mode changes due to button bouncing
  }

  // Update fading LEDs
  for (int x = 0; x < 21; x++) {
    // Check if the current LED segment is active (turned on)
    if (ledsActive[x]) {
      // Check if the time since the LED segment was turned on exceeds 500 milliseconds
      // If yes, it's time to start fading out the LED segment
      if (millis() - ledsActiveStartTime[x] >= 500) {
        ledsActive[x] = false;
        fadeValues[x] = 255; // Start fading out this LED segment
      }
    }
  }

  // RGB rainbow color handling:
  for (int x = 0; x < 21; x++) {
    if (ledsRBActive[x]) {
      if (millis() - ledsActiveStartTime[x] >= 400) {
        // Update the RGBValues to transition between colors in the sequence
        RGBValues[x]++;

        // Calculate the index of the first LED in the corresponding segment
        int ledIndex = (x - 1) * LEDS_PER_GROUP;

        // Update the color of the LEDs based on the current RGBValues
        // This sequence changes from Red to Violet and then starts again from Red
        if (RGBValues[x] == 1) {
          leds[ledIndex + 0] = CRGB(255, 0, 0);      // Red
          leds[ledIndex + 1] = CRGB(230, 40, 9);     // Orange
          leds[ledIndex + 2] = CRGB(230, 52, 24);    // Light Orange
        }
        else if (RGBValues[x] == 2) {
          leds[ledIndex + 0] = CRGB(230, 40, 9);     // Orange
          leds[ledIndex + 1] = CRGB(230, 52, 24);    // Light Orange
          leds[ledIndex + 2] = CRGB(255, 255, 0);    // Yellow
        }
        else if (RGBValues[x] == 3) {
          leds[ledIndex + 0] = CRGB(230, 50, 20);    // Light Orange
          leds[ledIndex + 1] = CRGB(255, 255, 0);    // Yellow
          leds[ledIndex + 2] = CRGB(45, 255, 45);    // Light Green
        }
        else if (RGBValues[x] == 4) {
          leds[ledIndex + 0] = CRGB(255, 255, 0);    // Yellow
          leds[ledIndex + 1] = CRGB(45, 255, 45);    // Light Green
          leds[ledIndex + 2] = CRGB(0, 128, 0);      // Green
        }
        else if (RGBValues[x] == 5) {
          leds[ledIndex + 0] = CRGB(45, 255, 45);      // Light Green
          leds[ledIndex + 1] = CRGB(0, 128, 0);      // Green
          leds[ledIndex + 2] = CRGB(0, 0, 255);      // Blue
        }
        else if (RGBValues[x] == 6) {
          leds[ledIndex + 0] = CRGB(0, 128, 0);      // Green
          leds[ledIndex + 1] = CRGB(0, 0, 255);      // Blue
          leds[ledIndex + 2] = CRGB(148, 0, 211);    // Violet
        }
        else if (RGBValues[x] == 7) {
          leds[ledIndex + 0] = CRGB(0, 0, 255);      // Blue
          leds[ledIndex + 1] = CRGB(148, 0, 211);    // Violet
          leds[ledIndex + 2] = CRGB(255, 0, 0);      // Red
        }
        else if (RGBValues[x] == 8) {
          leds[ledIndex + 0] = CRGB(148, 0, 211);    // Violet
          leds[ledIndex + 1] = CRGB(255, 0, 0);      // Red
          leds[ledIndex + 2] = CRGB(230, 40, 9);     // Orange
        }
        else if (RGBValues[x] == 9) {
          leds[ledIndex + 0] = CRGB(255, 0, 0);      // Red
          leds[ledIndex + 1] = CRGB(230, 40, 9);     // Orange
          leds[ledIndex + 2] = CRGB(255, 165, 0);    // Light Orange
        }

        // After the last color transition, reset the sequence and activate fading out
        if (RGBValues[x] == 10) {
          ledsRBActive[x] = false;
          ledsActive[x] = true;
          ledsActiveStartTime[x] = millis() - 501;
        }

        // Update the LEDs to show the new colors
        FastLED.show();
        ledsActiveStartTime[x] = millis();  // Record the time when the LEDs were updated
      }
    }
  }


  // Fade out LEDs that were turned on by button presses
  for (int x = 0; x < 21; x++) {
    if (fadeValues[x] > 0 && !ledsActive[x]) {
      int ledIndex = (x - 1) * LEDS_PER_GROUP;
      fadeValues[x]--;
      for (int i = 0; i < LEDS_PER_GROUP; i++) {
        leds[ledIndex + i].fadeToBlackBy(1);
      }
      FastLED.show();
    }
  }
}

// Function to light up LEDs based on button press and color mode
void LightLED(int buttonIN) {

  int ledIndex = (buttonIN - 1) * LEDS_PER_GROUP;
  // Special mode 8 activates the RGB sequence for the specific button
  if (mode == 8) {
    RGBValues[buttonIN] = 0;
    ledsRBActive[buttonIN] = true;
    ledsActiveStartTime[buttonIN] = millis() - 1000;
    leds[ledIndex + 0] = CRGB(255, 0, 0);      // Red
    leds[ledIndex + 1] = CRGB(230, 40, 9);     // Orange
    leds[ledIndex + 2] = CRGB(230, 50, 20);    // Light Orange
    FastLED.show();
  }
  // Mode 7 sets specific colors for each of the LEDs
  else if (mode == 7) {
    leds[ledIndex + 0] = CRGB(255, 30, 30);
    leds[ledIndex + 1] = CRGB::Yellow;
    leds[ledIndex + 2] = CRGB(20, 20, 255);
    ledsActive[buttonIN] = true; // Mark this LED segment as active
    ledsActiveStartTime[buttonIN] = millis(); // Record the time when it was turned ON
  }
  // Other modes set a specific color for the LEDs
  else {
    ledsActive[buttonIN] = true; // Mark this LED segment as active
    ledsActiveStartTime[buttonIN] = millis(); // Record the time when it was turned ON
    for (int i = 0; i < LEDS_PER_GROUP; i++) {
      leds[ledIndex + i] = getColor(mode);
    }
  }

  FastLED.show();  // Update the LEDs to show the new colors
}

// Function to get the color based on the color mode
CRGB getColor(int colorMode) {
  switch (colorMode) {
    case 0: return CRGB::Red;                // Red
    case 1: return CRGB::Green;              // Green
    case 2: return CRGB::Blue;               // Blue
    case 3: return CRGB::White;              // White
    case 4: return CRGB::Purple;             // Purple
    case 5: return CRGB(230, 40, 9);         // Orange
    case 6: return CRGB(50, 255, 20);        // Fluorescent Green

    default: return CRGB::Black;
  }
}

void changeCLR(int pos) {
  int ledIndex = (pos - 1) * LEDS_PER_GROUP;

  if(clrstate[pos]) {
    leds[ledIndex + 0] = CRGB(20, 20, 255);
    leds[ledIndex + 1] = CRGB(20, 20, 255);
    leds[ledIndex + 2] = CRGB(20, 20, 255);
  }
  else {
    leds[ledIndex + 0] = CRGB::Yellow;
    leds[ledIndex + 1] = CRGB::Yellow;
    leds[ledIndex + 2] = CRGB::Yellow;
  }
  FastLED.show();  // Update the LEDs to show the new colors
  
  delay(300);

}
$abcdeabcde151015202530354045505560fghijfghij
$abcdeabcde151015202530354045505560fghijfghij
$abcdeabcde151015202530fghijfghij