#include <FastLED.h>
#include <ezButton.h>  // the library to use for SW pin

#define CLK_PIN 2
#define DT_PIN 3
#define SW_PIN 4
#define LED_PIN 7

#define NUM_LEDS    14  // Set the number of LEDs in the ring + 1
#define BRIGHTNESS  255
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB

ezButton button(SW_PIN);  // create ezButton object that attach to SW_PIN
CRGB leds[NUM_LEDS];

enum ColorState {
    RED,
    BLUE,
    GREEN,
    YELLOW,
    CYAN,
    PURPLE
};


ColorState currentColor = RED;
int counter = 0; // Current LED index
int CLK_state;
int prev_CLK_state;

// Define LED states
enum LEDState {
    OFF,
    HALF_BRIGHT,
    FULL_BRIGHT
};

LEDState ledStates[NUM_LEDS]; // Array to hold the state of each LED

void setup() {
    Serial.begin(9600);
    pinMode(CLK_PIN, INPUT);
    pinMode(DT_PIN, INPUT);
    button.setDebounceTime(50);  // set debounce time to 50 milliseconds
    prev_CLK_state = digitalRead(CLK_PIN);
    
    // Initialize all LEDs to off
    for (int i = 0; i < NUM_LEDS; i++) {
        leds[i] = CRGB::Black;
        ledStates[i] = OFF; // Set all LEDs to OFF state
    }
    
    // Set the first LED to be always on
    leds[0] = getColor(currentColor); // Set the first LED to the current color
    ledStates[0] = FULL_BRIGHT; // Set its state to FULL_BRIGHT

    FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
    FastLED.setBrightness(BRIGHTNESS);
}

unsigned long lastDebounceTime = 0; // Last time the output pin was toggled
const unsigned long debounceDelay = 100; // Delay for debounce

void loop() {
    button.loop();  // MUST call the loop() function first
    CLK_state = digitalRead(CLK_PIN);

    if (CLK_state != prev_CLK_state && (millis() - lastDebounceTime) > debounceDelay) {
       lastDebounceTime = millis(); // Reset the debounce timer
       int new_CLK_state = digitalRead(CLK_PIN);
       if (new_CLK_state == CLK_state) { // Confirm the state is stable
         lastDebounceTime = millis(); // Reset the debounce timer


        if (digitalRead(DT_PIN) == LOW) {
            // Counter-clockwise direction
            if (counter > 0) { // Ensure counter does not go below 0
                // Handle CCW logic
                if (ledStates[counter] == FULL_BRIGHT) {
                    // Set to half brightness
                    leds[counter] = getColor(currentColor).fadeToBlackBy(128);
                    ledStates[counter] = HALF_BRIGHT;
                } else if (ledStates[counter] == HALF_BRIGHT) {
                    // Set to off
                    leds[counter] = CRGB::Black;
                    ledStates[counter] = OFF;
                //} else if (ledStates[counter] == OFF) {
                    // Move to the previous LED and set to full brightness
                    counter--;
                    if(counter > NUM_LEDS) {
                      leds[counter] = getColor(currentColor);
                      ledStates[counter] = FULL_BRIGHT;
                    }
                }
            }
        } else {
            // Clockwise direction
            if (counter < NUM_LEDS - 1) { // Ensure counter does not exceed NUM_LEDS - 1
                // Handle CW logic
                if (ledStates[counter] == OFF) {
                    // Set to half brightness
                    leds[counter] = getColor(currentColor).fadeToBlackBy(128);
                    ledStates[counter] = HALF_BRIGHT;
                } else if (ledStates[counter] == HALF_BRIGHT) {
                    // Set to full brightness
                    leds[counter] = getColor(currentColor);
                    ledStates[counter] = FULL_BRIGHT;
                } else if (ledStates[counter] == FULL_BRIGHT) {
                    // Move to the next LED and set to half brightness
                    counter++;
                    if (counter < NUM_LEDS) { 
                      leds[counter] = getColor(currentColor).fadeToBlackBy(128);
                      ledStates[counter] = HALF_BRIGHT;
                    }
                }
            }
        }

        Serial.print("COUNTER: ");
        Serial.println(counter);
    }
    }
    
    // Ensure the first LED is always on
    leds[0] = getColor(currentColor);
    ledStates[0] = FULL_BRIGHT;

    // Update the LEDs
    FastLED.show();
    prev_CLK_state = CLK_state;

    // Check if the button is pressed
    if (button.isPressed()) {
        Serial.println("Button Pressed!"); // Print message when button is pressed
        changeColor();
        
    }
}

// Function to get the current color based on the state
CRGB getColor(ColorState colorState) {
    switch (colorState) {
        case RED: return CRGB::Red;
        case BLUE: return CRGB::Blue;
        case GREEN: return CRGB::Green;
        case YELLOW: return CRGB::Yellow;
        case CYAN: return CRGB::Cyan;
        case PURPLE: return CRGB::Purple;
        default: return CRGB::Black;
    }
}

// Function to change the color state
void changeColor() {
    currentColor = static_cast<ColorState>((currentColor + 1) % 6); // Cycle through RED, BLUE, GREEN
    // Update all LEDs to the new color regardless of their state
    for (int i = 0; i < NUM_LEDS; i++) {
        // Change the color of the LED regardless of its state
        if (leds[i].r == 0 && leds[i].g == 0 && leds[i].b == 0) {
            // LED is off, just set its color without turning it on
            leds[i] = getColor(currentColor).fadeToBlackBy(255); // Keep it off but set the color
        } else if (ledStates[i] == HALF_BRIGHT) {
            // LED is half-bright, change its color but keep it half-bright
            leds[i] = getColor(currentColor).fadeToBlackBy(128); // Keep it at half brightness
        } else {
            // LED is fully bright, change its color
            leds[i] = getColor(currentColor);
        }
    }
    // Print the current color name
    switch (currentColor) {
        case RED: Serial.println("Current Color: RED"); break;
        case BLUE: Serial.println("Current Color: BLUE"); break;
        case GREEN: Serial.println("Current Color: GREEN"); break;
        case YELLOW: Serial.println("Current Color: YELLOW"); break;
        case CYAN: Serial.println("Current Color: CYAN"); break;
        case PURPLE: Serial.println("Current Color: PURPLE"); break;
    }
}

uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
encoder1:CLK
encoder1:DT
encoder1:SW
encoder1:VCC
encoder1:GND
led1:VDD
led1:DOUT
led1:VSS
led1:DIN
ring1:GND
ring1:VCC
ring1:DIN
ring1:DOUT