#include <LiquidCrystal_I2C.h> //kniznice displeju

//priradenie pinov k tlacidlam a bzuciaku a displeju
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int Buzzer = 7;
const int TimeUp = 6;
const int TimeDown = 5;
const int ModeChange = 3;
const int ValueSet = 4;


//vytvorenie premennych
int hours = 0;
int mins = 0;
int secs = 0;
int hoursAlarm = 0;
int minsAlarm = 0;
int secsAlarm = 0;
int Mod = 1;
int SettingValue = 0;

bool SettingTimeUp = false;
bool SettingTimeDown = false;
bool AlarmActive = false;
bool SettingTime = false;
// zaciatocny kod
void setup() {
  pinMode(TimeUp, INPUT_PULLUP);
  pinMode(TimeDown, INPUT_PULLUP);
  pinMode(ValueSet, INPUT_PULLUP);
  pinMode(ModeChange, INPUT_PULLUP);
  pinMode(Buzzer, OUTPUT);

  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.print("Cas");
}

void loop() {
  AktualizujCas(); //cas bezi

  if (hours == hoursAlarm && mins == minsAlarm && secs == secsAlarm)
  { //kontrola ci ma byt budik aktivny
    lcd.clear();
    lcd.print("Budik aktivny:");
    lcd.setCursor(0,1);
    VypisCasu();
    AlarmActive = true;
    Alarm();
    lcd.clear();
    Mod = 1;
    lcd.print("Cas");
    lcd.setCursor(0,1);
    VypisCasu();
  }
// nastavovanie času smerom DOLE
  if (digitalRead(TimeUp) == LOW || SettingTimeUp) {
    SettingTime = true;
    if (Mod == 1) //v pripade hodin: 
    { 
      if (SettingValue == 0) {
        hours++;
        
        if (hours >= 24) {
          lcd.clear();
          lcd.print("Cas");
          lcd.setCursor(0,1);
          hours = 0;
        }
      } else if (SettingValue == 1) {
        mins++;
        if (mins >= 60) {
          lcd.clear();
          lcd.print("Cas");
          lcd.setCursor(0,1);
          mins = 0;
        }
      }
    } 
    else if (Mod == 2) //v pripade budika 
    {
      if (SettingValue == 0) {
        SettingTime = false;
        hoursAlarm++;
        if (hoursAlarm >= 24) {
          lcd.clear();
          lcd.print("Budik");
          lcd.setCursor(0,1);
          hoursAlarm = 0;
        }
      } else if (SettingValue == 1) {
        SettingTime = false;
        minsAlarm++;
        if (minsAlarm >= 60) {
          lcd.clear();
          lcd.print("Budik");
          lcd.setCursor(0,1);
          minsAlarm = 0;
        }
      }
    }
    VypisCasu();
    delay(200); // Malá oneskorenie pre stabilné čítanie tlačidla
    SettingTime = false; // Resetujte premennú NastavujeCas
    SettingTimeUp = false;
  } 

// nastavovanie času smerom DOLE
if (digitalRead(TimeDown) == LOW || SettingTimeDown) {
    
    if (Mod == 1) //v pripade hodin: 
    {
      if (SettingValue == 0) {
        hours--;
        if (hours < 0) {
          lcd.clear();
          lcd.print("Cas");
          lcd.setCursor(0,1);
          hours = 23;
        }
        
      } else if (SettingValue == 1) {
        mins--;
        if (mins < 0) {
          lcd.clear();
          lcd.print("Cas");
          lcd.setCursor(0,1);
          mins = 59;
        }
      }
    } 
    
    else if (Mod == 2) //v pripade budika: 
    {
      if (SettingValue == 0) {
        SettingTime = false;
        hoursAlarm--;
        if (hoursAlarm < 0) {
          lcd.clear();
          lcd.print("Budik");
          lcd.setCursor(0,1);
          hoursAlarm = 23;
        }
      } else if (SettingValue == 1) {
        SettingTime = false;
        minsAlarm--;
        if (minsAlarm < 0) {
          lcd.clear();
          lcd.print("Budik");
          lcd.setCursor(0,1);
          minsAlarm = 59;
        }
      }
    }
    VypisCasu();
    delay(200); // Malá oneskorenie pre stabilné čítanie tlačidla
    SettingTime = false; // Resetujte premennú NastavujeCas
    
  } 

  if (digitalRead(ValueSet) == LOW && !SettingTime)   // prepinanie nastavovanej hodnoty = hodiny alebo minuty
  {
    SettingValue++;
    if (SettingValue > 1) {
      SettingValue = 0;
    }
    if (SettingValue == 0) {
      lcd.clear();
      lcd.print("Nastav Hodin");
      delay(500);
      lcd.clear();
    } 
    else if (SettingValue == 1)
    {
      lcd.clear();
      lcd.print("Nastav Minut");
      delay(500);
      lcd.clear();
    }
    if(Mod == 1)
    {
     lcd.print("Cas");
     VypisCasu();
    }
    else if(Mod == 2)
    {
      lcd.print("Budik");
      VypisCasu();
    }
    delay(200); // Malá oneskorenie pre stabilné čítanie tlačidla
  }

  //prepnutie modu
  if (digitalRead(ModeChange) == LOW && AlarmActive == false)  // prepinanie modu medzi budikom a hodinami
  {
    Mod++;
    if(Mod > 2)
    {
      Mod = 1;
    }
    if(Mod == 1)
    {
      lcd.clear();
      lcd.print("Cas");
      lcd.setCursor(0,1);
      VypisCasu();
    }
    else if(Mod == 2)
    {
      lcd.clear();
      lcd.print("Budik");
      lcd.setCursor(0,1);
      VypisCasu();
    }
  }
  else if (digitalRead(ModeChange) == HIGH)
  {
    AlarmActive = false;
  }

}

void AktualizujCas() //beh časua a jeho logika
{

  if (!SettingTime) 
  {
    // Kontrola stlačenia tlačidla CasHore aj po uplynutí jednej sekundy
    if (digitalRead(TimeUp) == LOW) {
      SettingTime = true;
      SettingTimeUp = true;
    }
    if(digitalRead(TimeDown) == LOW)
    {
      SettingTime = true;
      SettingTimeDown = true;
    }
  }
  if (!SettingTime) {
    secs++;
    if (secs >= 60) {
      secs = 0;
      mins++;
    }
    if (mins >= 60) {
      mins = 0;
      hours++;
    }
    if (hours >= 24) {
      hours = 0;
    }
      
    
    VypisCasu();
    delay(1000); // Každú sekundu
  }
}

void Alarm()  // funkcia zvonenia budika
{
  do
  {
    tone(Buzzer, 2000, 100);
    delay(300); //delay pre fungovanie pesničky budíka
  }while(digitalRead(ModeChange) == HIGH);
}

void VypisCasu() //vypis casu v oboch pripadoch(budik, hodiny) 
{
  if(Mod == 1)
  {
    lcd.setCursor(0,1);
    lcd.print(hours < 10 ? "0" : ""); // zabezpečuje zobrazenie hodin formáte 00:00:00, ak je premenna jednociferná tak pridá pred tú premennú cifru 0 aby sa dodržal formát
    lcd.print(hours);
    lcd.print(":");
    lcd.print(mins < 10 ? "0" : "");
    lcd.print(mins);
    lcd.print(":");
    lcd.print(secs < 10 ? "0" : "");
    lcd.print(secs);    
  }
  else if(Mod == 2)
  {
    lcd.setCursor(0,1);
    lcd.print(hoursAlarm < 10 ? "0" : ""); // zabezpečuje zobrazenie hodin formáte 00:00:00, ak je premenna jednociferná tak pridá pred tú premennú cifru 0 aby sa dodržal formát
    lcd.print(hoursAlarm);
    lcd.print(":");
    lcd.print(minsAlarm < 10 ? "0" : "");
    lcd.print(minsAlarm);
    lcd.print(":");
    lcd.print(secsAlarm < 10 ? "0" : "");
    lcd.print(secsAlarm);
  }

}