#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>

RTC_DS1307 rtc;
LiquidCrystal_I2C lcd(0x27, 16, 2);

#define nastavenie 4
#define plus 2
#define minus 3
#define HaM 5
#define BUZZER_PIN 6
bool buzzerActivated = false; // Deklarácia a inicializácia premennej

DateTime datumCas;

int minuta;
int hodina;
int sekunda;
int menu = 0;
int jednotka = 0;
bool plusPressed = false;
bool minusPressed = false;
unsigned long lastButtonTime = 0;
const unsigned long debounceDelay = 200; // Časová prodleva pro odstranění odskoku
int stlacenie = 0;
int buttonState4;
int lastDebounceTime4 = 0;
int reading4;

// richard
int AlarmMinuta;
int AlarmHodina;
int AlarmSekunda;



int stlacenie1 = 0;
int buttonState5;
int lastDebounceTime5 = 0;
int reading5;

void setup() {
  lcd.init(); // Inicializácia LCD displeja
  lcd.backlight(); // Zapnutie podsvietenia displeja
  pinMode(nastavenie, INPUT_PULLUP); // Nastavenie pinu pre tlačidlo "nastavenie" ako vstup s pull-up rezistorom
  pinMode(plus, INPUT_PULLUP); // Nastavenie pinu pre tlačidlo "plus" ako vstup s pull-up rezistorom
  pinMode(minus, INPUT_PULLUP); // Nastavenie pinu pre tlačidlo "minus" ako vstup s pull-up rezistorom
  pinMode(HaM, INPUT_PULLUP); // Nastavenie pinu pre tlačidlo "HaM" ako vstup s pull-up rezistorom
  pinMode(BUZZER_PIN, OUTPUT); // Nastavenie pinu pre buzzer ako výstup

  if (!rtc.begin()) { // Ak sa nepodarí inicializovať RTC modul
    lcd.print("Hodiny nejsou pripojeny!"); // Zobrazenie chybovej správy na displeji
    while (1); // Nekonečná slučka, zastaví vykonávanie programu
  }
  
  if (!rtc.isrunning()) { // Ak RTC modul nie je spustený (baterka bola vybraná alebo iná chyba)
    Serial.println("Hodiny nejsou spusteny! Spoustim nyni.."); // Výpis chybovej správy do sériového monitoru
    lcd.print("Nastavte cas:"); // Výpis inštrukcií pre nastavenie času na displej

    // Interaktívne nastavenie času
    while (true) { // Neustála slučka pre nastavenie času
      lcd.clear(); // Vymazanie obsahu displeja
      lcd.print("HH:MM"); // Výpis textu na displej pre zadanú hodinu a minútu
      lcd.setCursor(0, 1); // Nastavenie kurzoru na druhý riadok displeja
      lcd.print(">"); // Zobrazenie kurzoru na displeji

      int hodiny = 0; // Inicializácia premenných pre hodiny a minúty
      int minuty = 0;
      bool potvrzeno = false; // Príznak pre potvrdenie nastavenia času

      while (!potvrzeno) { // Neustála slučka pre interaktívne nastavenie hodín
        if (!digitalRead(plus)) { // Ak je stlačené tlačidlo "plus"
          hodiny = (hodiny + 1) % 24; // Zvýšenie hodiny o 1, pričom sa moduluje 24
          delay(250); // Krátka prestávka pre debounce
        }
        if (!digitalRead(minus)) { // Ak je stlačené tlačidlo "minus"
          hodiny = (hodiny + 23) % 24; // Zníženie hodiny o 1, pričom sa moduluje 24
          delay(250); // Krátka prestávka pre debounce
        }
        lcd.setCursor(0, 1); // Nastavenie kurzoru na druhý riadok displeja
        lcd.print(hodiny < 10 ? "0" : ""); // Formátovanie zobrazenia hodín s dodatočnou 0 pre jednociferné hodiny
        lcd.print(hodiny); // Výpis hodín na displej
        lcd.print(":"); // Výpis dvojbodky na displej
        lcd.print(minuty < 10 ? "0" : ""); // Formátovanie zobrazenia minút s dodatočnou 0 pre jednociferné minúty
        lcd.print(minuty); // Výpis minút na displej

        if (!digitalRead(nastavenie)) { // Ak je stlačené tlačidlo "nastavenie"
          potvrzeno = true; // Nastavenie príznaku pre potvrdenie nastavenia času
          delay(250); // Krátka prestávka pre debounce
        }
      }
      
      potvrzeno = false; // Resetovanie príznaku pre potvrdenie nastavenia času

      lcd.clear(); // Vymazanie obsahu displeja
      lcd.print("HH:MM"); // Výpis textu na displej pre zadanú hodinu a minútu
      lcd.setCursor(3, 1); // Nastavenie kurzoru na druhý riadok displeja
      lcd.print(">"); // Zobrazenie kurzoru na displeji

      while (!potvrzeno) { // Neustála slučka pre interaktívne nastavenie minút
        if (!digitalRead(plus)) { // Ak je stlačené tlačidlo "plus"
          minuty = (minuty + 1) % 60; // Zvýšenie minút o 1, pričom sa moduluje 60
          delay(250); // Krátka prestávka pre debounce
        }
        if (!digitalRead(minus)) { // Ak je stlačené tlačidlo "minus"
          minuty = (minuty + 59) % 60; // Zníženie minút o 1, pričom sa moduluje 60
          delay(250); // Krátka prestávka pre debounce
        }
        lcd.setCursor(0, 1); // Nastavenie kurzoru na druhý riadok displeja
        lcd.print(hodiny < 10 ? "0" : ""); // Formátovanie zobrazenia hodín s dodatočnou 0 pre jednociferné hodiny
        lcd.print(hodiny); // Výpis hodín na displej
        lcd.print(":"); // Výpis dvojbodky na displej
        lcd.print(minuty < 10 ? "0" : ""); // Formátovanie zobrazenia minút s dodatočnou 0 pre jednociferné minúty
        lcd.print(minuty); // Výpis minút na displej

        if (!digitalRead(nastavenie)) { // Ak je stlačené tlačidlo "nastavenie"
          potvrzeno = true; // Nastavenie príznaku pre potvrdenie nastavenia času
          delay(250); // Krátka prestávka pre debounce
        }
      }
      
      // Potvrdenie nastavenia času a zápis do RTC modulu
      lcd.clear(); // Vymazanie obsahu displeja
      lcd.print("Cas nastaven"); // Výpis potvrdenia nastavenia času na displej
      rtc.adjust(DateTime(2024, 4, 27, hodiny, minuty, 0)); // Nastavenie času v RTC module
      delay(2000); // Krátka prestávka pre zobrazenie potvrdenia na displeji
      break; // Ukocnenie nastavovania casu
    }
    lcd.clear(); // Vymazanie obsahu displeja po nastaveni casu
  }
}


void loop() {
  
  if ((millis() - lastDebounceTime4) > debounceDelay) {
    reading4 = digitalRead(nastavenie);
    if (reading4 != buttonState4) {
      buttonState4 = reading4;
      if (buttonState4 == LOW) {
        stlacenie++;
        if(stlacenie > 3) {
          stlacenie = 1;
        }
      }
    }
  }

  if ((millis() - lastDebounceTime5) > debounceDelay) {
    reading5 = digitalRead(HaM);
    if (reading5 != buttonState5) {
      buttonState5 = reading5;
      if (buttonState5 == LOW) {
        stlacenie1++;
        if(stlacenie1 > 2) {
          stlacenie1 = 1;
        }
      }
    }
  }

  datumCas = rtc.now();
  if (!digitalRead(nastavenie)) {
    menu++;
    jednotka++;
    delay(250);
    while (!digitalRead(nastavenie));
  }

  if (menu == 0) {
    AktualniCas(); 
    updateAlarm();
  }

  if (menu == 1) {
    if (jednotka == 1) {
      lcd.clear();
      jednotka = 0;
      stlacenie1 = 0;
    }
    MeniHodiny();
  }

  if (menu == 2) {
    if (jednotka == 1) {
      lcd.clear();
      jednotka = 0;
    }
    MeniAlarmu();
  }

  if (menu == 3) {
    lcd.clear();
    menu = 0; // Resetujeme menu zpět na zobrazení aktuálního času
    jednotka = 0; // Resetujeme jednotku
  }

  delay(250);
}



void AktualniCas() {
  datumCas = rtc.now();
  hodina = datumCas.hour();
  minuta = datumCas.minute();
  sekunda = datumCas.second();
  
  lcd.setCursor(0,0);
  lcd.print("Cas: ");
  lcd.setCursor(5,0);
  lcd.print(hodina);
  lcd.setCursor(7,0);
  lcd.print(':');
  lcd.setCursor(8,0);
  lcd.print(minuta);
  lcd.setCursor(10,0);
  lcd.print(':');
  lcd.setCursor(11,0);
  lcd.print(sekunda);
  
  // Zobrazenie režimu H alebo M na základe stlačenia tlačidla HaM
}

void MeniHodiny() {
  unsigned long currentMillis = millis();
  
  if (stlacenie == 1) {
    if (!digitalRead(plus) && !plusPressed && (currentMillis - lastButtonTime >= debounceDelay)) {
      plusPressed = true;
      lastButtonTime = currentMillis;
      if (stlacenie1 == 1) { // Ak je režim nastavený na M (minúty)
        minuta++; // Zvýšiť hodnotu minút
        if (minuta > 59) {
          minuta = 0;
        }
      } else { // Ak je režim nastavený na H (hodiny)
        hodina++; // Zvýšiť hodnotu hodín
        if (hodina > 23) {
          hodina = 0;
        }
      }
    }
    if (digitalRead(plus)) {
      plusPressed = false;
    }
    
    if (!digitalRead(minus) && !minusPressed && (currentMillis - lastButtonTime >= debounceDelay)) {
      minusPressed = true;
      lastButtonTime = currentMillis;
      if (stlacenie1 == 1) { // Ak je režim nastavený na M (minúty)
        minuta--; // Znížiť hodnotu minút
        if (minuta < 0) {
          minuta = 59;
        }
      } else { // Ak je režim nastavený na H (hodiny)
        hodina--; // Znížiť hodnotu hodín
        if (hodina < 0) {
          hodina = 23;
        }
      }
    }
    if (digitalRead(minus)) {
      minusPressed = false;
    }

    // Formátovanie hodín na dve číslice
    char formattedHour[3]; // Pole na formátovaný čas
    sprintf(formattedHour, "%02d", hodina); // Formátovanie hodiny

    char formattedMinute[3]; // Pole na formátované minúty
    sprintf(formattedMinute, "%02d", minuta); // Formátovanie minút

    lcd.setCursor(0,0);
    lcd.print("Zmena casu");

    // Vyčistenie druhej pozície
    lcd.setCursor(1,1);
    lcd.print(" "); 

    lcd.setCursor(0,1);
    lcd.print(formattedHour); // Zobrazenie formátovanej hodiny
    lcd.setCursor(2,1);
    lcd.print(':');
    lcd.setCursor(3,1);
    lcd.print(formattedMinute);
    lcd.setCursor(5,1);
    lcd.print(':');
    lcd.setCursor(6,1);
    lcd.print(sekunda); // Aktualizovaná hodnota sekundy
  

    
    // Zobrazenie režimu H alebo M na základe stlačenia tlačidla HaM
     lcd.setCursor(15,1);
  if (stlacenie1 == 1) {
    lcd.print("M");
  } else{
    lcd.print("H");
  }
  }
  
  
  else if (stlacenie == 2) {
    lcd.setCursor(0, 0);
    lcd.print("Zmena alarmu");
    // Implementace kódu pro nastavení alarmu
  }
}

void MeniAlarmu() {
  unsigned long currentMillis = millis();
  
  AlarmMinuta = minuta;
  AlarmHodina = hodina;

  // Zmena hodnoty hodin alarmu
  if (!digitalRead(plus) && !plusPressed && (currentMillis - lastButtonTime >= debounceDelay)) {
    plusPressed = true;
    lastButtonTime = currentMillis;
    if (stlacenie1 == 1) { // Ak je režim nastavený na M (minúty)
      minuta++;
      AlarmMinuta = minuta; // Zvýšiť hodnotu minút
      if (minuta > 59) {
        minuta = 0;
      }
      buzzerActivated = false; // Nastavíme príznak na false, pretože sme zmenili čas
    } else { // Ak je režim nastavený na H (hodiny)
      hodina++;
      AlarmHodina = hodina; // Zvýšiť hodnotu hodín
      if (hodina > 23) {
        hodina = 0;
      }
      buzzerActivated = false; // Nastavíme príznak na false, pretože sme zmenili čas
    }
  }
  if (digitalRead(plus)) {
    plusPressed = false;
  }
  
  if (!digitalRead(minus) && !minusPressed && (currentMillis - lastButtonTime >= debounceDelay)) {
    minusPressed = true;
    lastButtonTime = currentMillis;
    if (stlacenie1 == 1) { // Ak je režim nastavený na M (minúty)
      minuta--;
      AlarmMinuta = minuta; // Znížiť hodnotu minút
      if (minuta < 0) {
        minuta = 59;
      }
      buzzerActivated = false; // Nastavíme príznak na false, pretože sme zmenili čas
    } else { // Ak je režim nastavený na H (hodiny)
      hodina--;
      AlarmHodina = hodina; // Znížiť hodnotu hodín
      if (hodina < 0) {
        hodina = 23;
      }
      buzzerActivated = false; // Nastavíme príznak na false, pretože sme zmenili čas
    }
  }
  if (digitalRead(minus)) {
    minusPressed = false;
  }

  // Formátovanie hodín na dve číslice
  char formattedHour[3]; // Pole na formátovaný čas
  sprintf(formattedHour, "%02d", hodina); // Formátovanie hodiny

  char formattedMinute[3]; // Pole na formátované minúty
  sprintf(formattedMinute, "%02d", minuta); // Formátovanie minút

  lcd.setCursor(0, 0);
  lcd.print("Zmena alarmu");

  // Vyčistenie druhej pozície
  lcd.setCursor(1, 1);
  lcd.print(" "); 

  // Zobrazenie formátovanej hodiny
  lcd.setCursor(0, 1);
  lcd.print(formattedHour); 
  lcd.setCursor(2, 1);
  lcd.print(':');
  lcd.setCursor(3, 1);
  lcd.print(formattedMinute);
  lcd.setCursor(5, 1);
  lcd.print(':');
  lcd.setCursor(6, 1);
  lcd.print(sekunda); 

  // Zobrazenie H alebo M na konci riadku v závislosti na stlačení tlačidla
  lcd.setCursor(15, 1);
  if (stlacenie1 == 1) {
    lcd.print("M");
  } else{
    lcd.print("H");
  }

  // Spustenie zvonenia buzzeru, ak je čas nastavenia alarmu rovnaký ako aktuálny č
}

void updateAlarm() {
  // Získanie aktuálneho času z RTC modulu
  DateTime now = rtc.now();

  // Porovnanie času nastaveného užívateľom s aktuálnym časom
  if (now.hour() == AlarmHodina && now.minute() == AlarmMinuta && !buzzerActivated) {
    // Ak sa časy zhodujú a príznak nie je nastavený, spustíme zvonenie buzzeru
    tone(BUZZER_PIN, 1000, 2000);
    
    //noTone(BUZZER_PIN); // Vypnutie zvonenia
    AlarmHodina = 0;
    AlarmMinuta = 0;

    buzzerActivated = true; // Nastavíme príznak, že zvonenie bolo spustené
    Serial.println("Buzzer: " + buzzerActivated);
  }
}













GND5VSDASCLSQWRTCDS1307+