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

// Name des RTC-Moduls 
RTC_DS1307 rtc; 

LiquidCrystal_I2C lcd(0x27, 20, 4); 

int Lautsprecher = 5;
int TasterLinks = 7;
int TasterRechts = 8;
int TasterStop = 9;

// Beginn der Weckzeit
int StundeWeckzeit = 15;
int MinuteWeckzeit = 37;

int StundeUhrzeit = 0;
int MinuteUhrzeit = 0;

// Dauer des Signal
int DauerWecksignal = 20;
// Flagge für das Stoppen vom Wecker
int WeckerGestoppt = 0;
// Flagge zum Signalisieren des Weckers, 1 Wenn Wecker klingelt, 0 wenn nicht.
int WeckerKlingelt = 0;
// Flagge für die Zeit Umstellung
int ZeitUmstellen = 0;
// Flagge für die Weckzeit Umstelllung
int WeckerUmstellen = 1;
// Beim aller ersten Drücken wird die Uhrzeitumstellung freigeschaltet.

int aktuelleMinute = 0;
int aktuelleStunde = 0;

// // Zeit messen für Ticken der Uhr
// long Startzeit;
// long ZeitJetzt;


// Setup
void setup()
{
  pinMode(TasterLinks, INPUT_PULLUP);
  pinMode(TasterRechts, INPUT_PULLUP);
  pinMode(TasterStop, INPUT_PULLUP);

  rtc.begin();

  // LCD initialisieren
  lcd.init();
  lcd.backlight();

}

// Interrupt Funktion
// Wecker ausschalten, Flagge setzten.
void Umstellung() 
{
  // Wecker klingelt, stoppen.
  if (WeckerKlingelt == 1) 
  {
    noTone(Lautsprecher);
    WeckerGestoppt = 1;
    WeckerKlingelt = 0;
    return;
  }
  // Wecker klingelt nicht. Zwischen Zeitumstellung und Weckerumstellung wechseln.
  else
  {
    if (WeckerUmstellen == 1)
    {
      // Jetzt die Zeit umstellen.
      WeckerUmstellen = 0;
      ZeitUmstellen = 1;
      lcd.setCursor(17, 3);
      lcd.print(" ");
      lcd.setCursor(10, 2);
      lcd.print("*");

    }
    else 
    {
      // Jetzt den Wecker umstellen.
      WeckerUmstellen = 1;
      ZeitUmstellen = 0;
      lcd.setCursor(10, 2);
      lcd.print(" ");
      lcd.setCursor(17, 3);
      lcd.print("*");
    }
  }
}



// Loop
void loop()
{
  String Stunde, Minute, Weckzeit;


  if (digitalRead(TasterStop) == LOW) 
  {
    // Entprellen
    delay(5);
    if (digitalRead(TasterStop) == LOW) 
    {
      Umstellung();
    }
    while (digitalRead(3) == LOW)
    {
      // warten
    }
  }
  
  // Stunde einstellen Wecker oder Uhrzeit
  // Flaggen abfragen.
  if (digitalRead(TasterLinks) == LOW)
  {
    // Wecker Umstellen
    if (WeckerUmstellen == 1)
    {
      delay(200);
      if (StundeWeckzeit >= 24) {
        StundeWeckzeit = 1;
      }
      else 
      { 
        StundeWeckzeit ++;
      }
    }
    // Uhrzeit umstellen.
    else if (ZeitUmstellen == 1)
    {
       delay(200);
        if (StundeUhrzeit >= 24) {
          StundeUhrzeit = 1;
        }
        else 
        { 
          StundeUhrzeit ++;
        }
    }
  }

  // Minuten Einstellen Wecker oder Uhrzeit
  if (digitalRead(TasterRechts) == LOW)
  {
    if (WeckerUmstellen == 1)
    {
      delay(200);
      if (MinuteWeckzeit >= 59) { 
        MinuteWeckzeit = 0;
      }
      else { 
        MinuteWeckzeit ++;
      }
    }
    else if (ZeitUmstellen == 1)
    {
      delay(200);
      if (MinuteUhrzeit >= 59) { 
        MinuteUhrzeit = 0;
      }
      else 
      { 
        MinuteUhrzeit ++;
      }
    }
  }
 
  // aktuelle Zeit lesen
  DateTime aktuell = rtc.now();
 
  // Position für Wochentag
  lcd.setCursor(0, 0);

  /*
    Wochentag anzeigen
    0 = Sonntag
    1 = Montag
    ...
    6 = Samstag
  */
  switch (aktuell.dayOfTheWeek())
  {
    case 0:
      lcd.print("Sonntag");
      break;
    case 1:
      lcd.print("Montag");
      break;
    case 2:
      lcd.print("Dienstag");
      break;
    case 3:
      lcd.print("Mittwoch");
      break;
    case 4:
      lcd.print("Donnerstag");
      break;
    case 5:
      lcd.print("Freitag");
      break;
    case 6:
      lcd.print("Samstag");
      break;
  }

  // Position für Tag, Monat und Jahr.
  lcd.setCursor(0, 1);
  lcd.print(aktuell.day());
  lcd.print(".");

  lcd.print(" ");

  switch (aktuell.month())
  {
    case 1:
      lcd.print("Januar");
      break;
    case 2:
      lcd.print("Februar");
      break;
    case 3:
      lcd.print("M\341rz");
      break;
    case 4:
      lcd.print("April");
      break;
    case 5:
      lcd.print("Mai");
      break;
    case 6:
      lcd.print("Juni");
      break;
    case 7:
      lcd.print("Juli");
      break;
    case 8:
      lcd.print("August");
      break;
    case 9:
      lcd.print("September");
      break;
    case 10:
      lcd.print("Oktober");
      break;
    case 11:
      lcd.print("November");
      break;
    case 12:
      lcd.print("Dezember");
      break;
  }
  lcd.print(" ");

  lcd.print(aktuell.year());
  
  // Position für Uhrzeit
  lcd.setCursor(0, 2);

  // wenn Stunden < 10 -> führende 0 setzen
  aktuelleStunde = (aktuell.hour() + StundeUhrzeit) % 24;
  // if (aktuelleStunde > 24)
  // {
  //   aktuelleStunde = 1 + StundeUhrzeit;
    
  // }

  // if (aktuell.hour() < 10) lcd.print("0");
  if (aktuelleStunde < 10)
  {
    lcd.print("0");
  }

  lcd.print(aktuelleStunde);
  // lcd.print(aktuell.hour())
  lcd.print(':');

  // wenn Minuten < 10 -> führende 0 setzen

  aktuelleMinute = (aktuell.minute() + MinuteUhrzeit) % 60;
  // if (aktuell.minute() < 10) lcd.print("0");
  if (aktuelleMinute < 10)
  {
    lcd.print("0");
  }
  // lcd.print(aktuell.minute());
  lcd.print(aktuelleMinute);
  lcd.print(':');

  // wenn Sekunden < 10 -> führende 0 setzen
  if (aktuell.second() < 10) lcd.print("0");
  lcd.print(aktuell.second());

  /*
    Weckzeit formatieren -> führende 0 ergänzen
    4 mögliche Fälle
    Stunde < 10 Minute < 10
    Stunde < 10 Minute > 9
    Stunde > 10 Minute < 10
    Stunde > 10 Minute > 9
  */
  if (StundeWeckzeit < 10 && MinuteWeckzeit < 10) {
    Weckzeit = "0" + String(StundeWeckzeit) + ":0" + String(MinuteWeckzeit);
  }

  if (StundeWeckzeit < 10 && MinuteWeckzeit > 9) {
    Weckzeit = "0" + String(StundeWeckzeit) + ":" + String(MinuteWeckzeit);
  }

  if (StundeWeckzeit > 9 && MinuteWeckzeit < 10) {
    Weckzeit = String(StundeWeckzeit) + ":0" + String(MinuteWeckzeit);
  }

  if (StundeWeckzeit > 9 && MinuteWeckzeit > 9) {
    Weckzeit = String(StundeWeckzeit) + ":" + String(MinuteWeckzeit);
  }

  lcd.setCursor(0, 3);
  lcd.print("Weckzeit: " + Weckzeit);

  // führende 0 setzen
  // if (aktuell.hour() < 10) {
  //   Stunde = "0" + String(aktuell.hour());
  // }
  // else {
  //   Stunde = String(aktuell.hour());
  // }
  if (aktuelleStunde < 10) {
    Stunde = "0" + String(aktuelleStunde);
  }
  else {
    Stunde = String(aktuelleStunde);
  }
  // führende 0 setzen
  // if (aktuell.minute() < 10) {
  //   Minute = "0" + String(aktuell.minute());
  // }
  if (aktuelleMinute < 10) {
    Minute = "0" + String(aktuelleMinute);
  }  
   
  else Minute = String(aktuelleMinute);

  // String zusammensetzen
  String aktuelleZeit = Stunde + ":" + Minute;
  
  // Bedingungen für den Wecker:
  // aktuelle Zeit muss die Weckzeit entsprechen
  // Der Wecker muss während den ersten 5 Sekunden der Minute aktiv sein (außer es wird gestoppt)

  if (aktuelleZeit == Weckzeit && aktuell.second() <  DauerWecksignal
  && WeckerGestoppt == 0 )
  {
    WeckerKlingelt = 1;
    tone(Lautsprecher, 1000, 50);
  }

  // Stoppen zurücksetzen, wenn die ersten 5 Sekunden vorbei sind.
  if (aktuell.second() >= DauerWecksignal) {
    WeckerGestoppt = 0;
  }
  /*
    Ticken der Uhr
    aktuelle Zeit (ZeitJetzt) messen
    millis() -> Zeit, die seit dem Start des Programms
    vergangen ist
    wenn die Differenz zwischen der gerade gemessenen Zeit
    und der im setup gemessenen Startzeit >= 1000 (1 Sekunde) ist
    -> kurzen Ton wiedergeben
    Startzeit muss anschließend auf die aktuelle Zeit gesetzt werden
  */
}

GND5VSDASCLSQWRTCDS1307+