#include <Adafruit_NeoPixel.h>
#include <Wire.h>
#include "RTClib.h"

#define PIN 25 // Pinnen vi bruker til Neopixlene
#define LYD1 32 // Liten lydbølge 4px
#define LYD2 33 // Mellom lydbølge 6px
#define LYD3 12 // Stor lydbølge 8px
#define MICROFON 35 // AI
#define NUMPIXELS 60 // Antall neopixler på en hel sirkel
#define PIN_IN1 26
#define PIN_IN2 27
#define SW_PIN 14

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel lStrip = Adafruit_NeoPixel(4, LYD1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel mStrip = Adafruit_NeoPixel(6, LYD2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel sStrip = Adafruit_NeoPixel(8, LYD3, NEO_GRB + NEO_KHZ800);
RTC_DS1307 rtc;

int pixelCount = 0;
bool inMenu = false;
bool countingDown = false;

volatile int lastEncoded = 0;
volatile long encoderValue = 0;
int lastMSB = 0;
int lastLSB = 0;

void setup() {
  Serial.begin(115200);
  
  strip.begin();
  strip.show(); // Setter alle pixlene til 'AV'
  lStrip.begin();
  lStrip.show(); // Setter alle pixlene til 'AV'
  mStrip.begin();
  mStrip.show(); // Setter alle pixlene til 'AV'
  sStrip.begin();
  sStrip.show(); // Setter alle pixlene til 'AV'
  
  pinMode(SW_PIN, INPUT_PULLUP);
  pinMode(PIN_IN1, INPUT);
  pinMode(PIN_IN2, INPUT);

  attachInterrupt(digitalPinToInterrupt(PIN_IN1), updateEncoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(PIN_IN2), updateEncoder, CHANGE);

  if (!rtc.begin()) {
    Serial.println("Kan ikke finne klokken, kanskje tom for batteri??");
    Serial.flush();
    abort();
  }
  if (!rtc.isrunning()) {
    Serial.println("Klokken er feil!");
  }

  Serial.println("Setup ferdig!");
}

void loop() {
  if (Serial.available()) {
    String kommando = Serial.readStringUntil('\n');
    if (kommando == "tid") {
      stillKlokke();
    }
  }

  if (digitalRead(SW_PIN) == LOW) {
    delay(50); // Debounce delay
    if (digitalRead(SW_PIN) == LOW) {
      if (countingDown) {
        countingDown = false;
        inMenu = false;
        strip.clear();
        strip.show();
      } else {
        inMenu = !inMenu;
        if (!inMenu) {
          startCountdown();
        }
      }
      while (digitalRead(SW_PIN) == LOW); // Wait for button release
    }
  }

  if (inMenu) {
    showMenu();
  } else if (countingDown) {
    countdown();
  } else {
    showClock();
  }
}

void showClock() {
  DateTime now = rtc.now();
  
  Serial.print("Klokken er: ");
  Serial.print(now.hour());
  Serial.print(":");
  Serial.print(now.minute());
  Serial.print(":");
  Serial.println(now.second());
  Serial.print("Dag i uken: ");
  Serial.println(now.dayOfTheWeek());
  
  strip.clear(); 
  klokke(now.hour(), now.minute(), now.second());
  strip.show();
  lStrip.show();
  mStrip.show();
  sStrip.show();
  delay(100);
}

void showMenu() {
  static long oldPosition = -999;
  long newPosition = encoderValue / 4;

  Serial.print("Encoder posisjon: ");
  Serial.println(newPosition);

  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    pixelCount = constrain(newPosition, 0, NUMPIXELS - 1);
    strip.clear();
    for (int i = 0; i <= pixelCount; i++) {
      strip.setPixelColor(i, strip.Color(255, 0, 0)); // Red color
    }
    strip.show();
  }
}

void startCountdown() {
  countingDown = true;
}

void countdown() {
  for (int i = pixelCount; i >= 0; i--) {
    strip.clear();
    for (int j = 0; j < i; j++) {
      strip.setPixelColor(j, strip.Color(255, 0, 0)); // Red color
    }
    strip.show();
    delay(1000); // 1 second delay
    if (digitalRead(SW_PIN) == LOW) {
      delay(50); // Debounce delay
      if (digitalRead(SW_PIN) == LOW) {
        countingDown = false;
        inMenu = false;
        strip.clear();
        strip.show();
        while (digitalRead(SW_PIN) == LOW); // Wait for button release
        break;
      }
    }
  }
  countingDown = false;
  inMenu = false;
  strip.clear();
  strip.show();
}

void klokke(int tim, int min, int sek) {
  int minuttsiden = tim * 60 + min; // Antall minutter siden kl. 12 eller 00
  int sekunditimen = min * 60 + sek; // Antall sekunder siden sist hele time
  
  // Sett timeviser
  int timePixel = map(minuttsiden, 0, 719, 0, NUMPIXELS - 1); // 60min x 12tim = 720min
  strip.setPixelColor(timePixel, strip.Color(0, 0, 100)); // Grønn pixel som viser timehånden
  // Sett minuttviser
  int minuttPixel = map(sekunditimen, 0, 3599, 0, NUMPIXELS - 1);
  strip.setPixelColor(minuttPixel, strip.Color(0, 100, 0)); // Rød pixel som viser minutthånden
  
  strip.setPixelColor(sek, strip.Color(50, 50, 50)); // Rød pixel som viser minutthånden
  for (int i = 0; i <= 3; i++) {
    lStrip.setPixelColor(i, strip.Color(0, 100, 0));
  }
  for (int i = 0; i <= 5; i++) {
    mStrip.setPixelColor(i, strip.Color(100, 100, 0));
  }
  for (int i = 0; i <= 7; i++) {
    sStrip.setPixelColor(i, strip.Color(100, 0, 0));
  }
}

void stillKlokke() {
  Serial.println("Skriv inn nytt klokkeslett (hh:mm:ss):");
  while (Serial.available() == 0); // Vent på input fra brukeren
  
  String tidInput = Serial.readStringUntil('\n'); // Les inn input fra brukeren
  int timer, minutt, sekund;
  sscanf(tidInput.c_str(), "%d:%d:%d", &timer, &minutt, &sekund); // Parse tiden
  
  Serial.println("Skriv inn ukedag (1-7, der 1=mandag og 7=søndag):");
  while (Serial.available() == 0); // Vent på input fra brukeren
  
  int ukedag = Serial.parseInt() + 1; // Les inn ukedagen
  
  // Oppdater RTC-klokken
  DateTime nyTid = DateTime(2023, 1, ukedag, timer, minutt, sekund); // Dummy dato
  rtc.adjust(nyTid);
  Serial.println("Klokken er oppdatert!");
}

void updateEncoder() {
  int MSB = digitalRead(PIN_IN1); // MSB = most significant bit
  int LSB = digitalRead(PIN_IN2); // LSB = least significant bit

  int encoded = (MSB << 1) | LSB; // Converting the 2 pin value to single number
  int sum = (lastEncoded << 2) | encoded; // Adding it to the previous encoded value

  if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue++;
  if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue--;

  lastEncoded = encoded; // Store this value for next time
}
GND5VSDASCLSQWRTCDS1307+