#include <Adafruit_NeoPixel.h>
#include <TimeLib.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define PIN            6
#define NUM_LEDS       60

#define SCREEN_WIDTH   128
#define SCREEN_HEIGHT  64
#define OLED_RESET     -1
#define SSD1306_I2C_ADDRESS 0x3C

#define BTN_ADD_PIN    2
#define BTN_SUB_PIN    3
#define BTN_ENTER_PIN  4

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

unsigned long previousMillis = 0;
const long interval = 1000;

int settingState = 0;
int settingValue = 0;
int maxSettingValue[] = {23, 59, 59};

unsigned long lastButtonPressMillis = 0;
const unsigned long debounceDelay = 200;

void setup() {
  Serial.begin(9600);
  strip.begin();
  strip.show();

  setTime(12, 0, 0, 1, 1, 2022); // Initial time setup

  if (!display.begin(SSD1306_SWITCHCAPVCC, SSD1306_I2C_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;) ;
  }
  display.clearDisplay();

  pinMode(BTN_ADD_PIN, INPUT_PULLUP);
  pinMode(BTN_SUB_PIN, INPUT_PULLUP);
  pinMode(BTN_ENTER_PIN, INPUT_PULLUP);
}

void setAllColor(uint32_t color) {
  for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, color);
  }
  strip.show();
}

void updateClock() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    int seconds = second();
    int minutes = minute();
    int hours = hour();

    int secondsLED = map(seconds, 0, 59, 0, NUM_LEDS - 1);
    int minutesLED = map(minutes, 0, 59, 0, NUM_LEDS - 1);
    int hoursLED = map(hours % 12, 0, 11, 0, NUM_LEDS - 1);

    setAllColor(strip.Color(0, 0, 0));
    strip.setPixelColor(secondsLED, strip.Color(0, 0, 255));
    strip.setPixelColor(minutesLED, strip.Color(0, 255, 0));
    strip.setPixelColor(hoursLED, strip.Color(255, 0, 0));
    strip.show();

    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 0);

    if (settingState == 0) {
      display.print("Time: ");
      display.print(hours);
      display.print(":");
      if (minutes < 10) display.print("0");
      display.print(minutes);
      display.print(":");
      if (seconds < 10) display.print("0");
      display.print(seconds);
    } else {
      display.print("Set: ");
      switch (settingState) {
        case 1:
          display.print("Hours ");
          break;
        case 2:
          display.print("Minutes ");
          break;
        case 3:
          display.print("Seconds ");
          break;
      }
      display.print(settingValue);
    }

    display.display();
  }
}

void handleButtons() {
    unsigned long currentMillis = millis();

    if (currentMillis - lastButtonPressMillis >= debounceDelay) {
        if (digitalRead(BTN_ADD_PIN) == LOW) {
            if (settingState == 0) {
                settingState = 1;  // Enter setting hours mode
                settingValue = hour();
            } else {
                settingValue = (settingValue + 1) % (maxSettingValue[settingState - 1] + 1);
            }
            lastButtonPressMillis = currentMillis;
        }

        if (digitalRead(BTN_SUB_PIN) == LOW) {
            if (settingState == 0) {
                settingState = 1;  // Enter setting hours mode
                settingValue = hour();
            } else {
                settingValue = (settingValue - 1 + maxSettingValue[settingState - 1] + 1) % (maxSettingValue[settingState - 1] + 1);
            }
            lastButtonPressMillis = currentMillis;
        }

        if (digitalRead(BTN_ENTER_PIN) == LOW) {
            if (settingState == 0) {
                settingState = 1;  // Enter setting hours mode
                settingValue = hour();
            } else if (settingState == 3) {
                // Set the time when finishing the setting sequence
                setTime(settingValue, minute(), second(), day(), month(), year());
                settingState = 0;  // Exit setting mode
            } else {
                // Increment the setting state and update the setting value
                settingState++;
                settingValue = (settingState == 1) ? hour() : (settingState == 2) ? minute() : second();
            }
            lastButtonPressMillis = currentMillis;
        }
    }
}

void loop() {
    updateClock();
    handleButtons();
}
nano:12
nano:11
nano:10
nano:9
nano:8
nano:7
nano:6
nano:5
nano:4
nano:3
nano:2
nano:GND.2
nano:RESET.2
nano:0
nano:1
nano:13
nano:3.3V
nano:AREF
nano:A0
nano:A1
nano:A2
nano:A3
nano:A4
nano:A5
nano:A6
nano:A7
nano:5V
nano:RESET
nano:GND.1
nano:VIN
nano:12.2
nano:5V.2
nano:13.2
nano:11.2
nano:RESET.3
nano:GND.3
ring1:GND
ring1:VCC
ring1:DIN
ring1:DOUT
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
btn3:1.l
btn3:2.l
btn3:1.r
btn3:2.r
oled1:GND
oled1:VCC
oled1:SCL
oled1:SDA