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

RTC_DS3231 rtc;

#define relay1 19
#define relay2 18
#define relay3 5
#define relay4 17
#define recv 34

#define pushbutton1 16
#define pushbutton2 4
#define pushbutton3 0
#define pushbutton4 2

int setButton1=25; // Button SET MENU' Red
int setButton2=26; // Button + Green
int setButton3=27; // Button - Blue
int setButton4=14; // Button SET TIMER Yellow

char cursorChar = '_';
enum TimerSetting { ON_HOUR, ON_MINUTE, OFF_HOUR, OFF_MINUTE };
TimerSetting timerSetting = ON_HOUR;

int relayPins[] = {19, 18, 5, 17};

IRrecv recv_pin(recv);
LiquidCrystal_I2C lcd(0x27, 20, 4);

//************Variables Used Including New Debounce Variable**************//
int hourupg;
int minupg;
int yearupg;
int monthupg;
int dayupg;
int menu=0;
int timerHour = 0;
int timerMin = 0;
int selectedRelay = 0;


//*** new
int onHour = 0;
int onMinute = 0;
int offHour = 0;
int offMinute = 0;
//************************************

const int debounce = 300;


bool led1State = false;
bool led2State = false;
bool led3State = false;
bool led4State = false;

bool settingTime = false;
int setLedIndex = 1;

void setup() {
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);

  pinMode(pushbutton1, INPUT_PULLUP);
  pinMode(pushbutton2, INPUT_PULLUP);
  pinMode(pushbutton3, INPUT_PULLUP);
  pinMode(pushbutton4, INPUT_PULLUP);

  pinMode(setButton1, INPUT_PULLUP);
  pinMode(setButton2, INPUT_PULLUP);
  pinMode(setButton3, INPUT_PULLUP);
  pinMode(setButton4, INPUT_PULLUP);

  lcd.init(); 
  lcd.clear();
  lcd.backlight();

  recv_pin.enableIRIn();
  recv_pin.blink13(true);

  for (int i = 0; i < 4; i++) {
    pinMode(relayPins[i], OUTPUT);
    digitalWrite(relayPins[i], LOW);
  }

  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, let's set the time!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
}

void loop() {
  

  // in which subroutine should we go?
  if (menu==0)
    {
     DisplayDateTime(); // void DisplayDateTime
    }
  if (menu==1)
    {
    DisplaySetHour();
    }
  if (menu==2)
    {
    DisplaySetMinute();
    }
  if (menu==3)
    {
    DisplaySetYear();
    }
  if (menu==4)
    {
    DisplaySetMonth();
    }
  if (menu==5)
    {
    DisplaySetDay();
    }
  if (menu==6)
    {
    StoreAgg(); 
    }
  if (menu==7)
    {
      DisplaySetTimer();
    }
  if (menu == 8) 
    {
    AdjustTimer();
    }
    StoreTimer();
    
    //delay(500);
    

    menu=0;
    delay(50);
}


void checkPushButton(int buttonPin, int ledIndex) {
  if (digitalRead(buttonPin) == LOW) {
    toggleLED(ledIndex);
    delay(500); 
  }
}

void checkSetButton(int setButtonPin, int ledIndex) {
  if (digitalRead(setButtonPin) == LOW) {
    settingTime = true;
    setLedIndex = ledIndex + 1;
    lcd.clear();
    lcd.print("Setting LED");
    lcd.setCursor(0, 1);
    lcd.print(setLedIndex);
    delay(500); 
  }
}
void PrintTwoDigits(int number) {
  if (number <= 9) {
    lcd.print("0");
  }
  lcd.print(number, DEC);
}

void DisplaySetTimer() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Select Relay:");
  lcd.setCursor(0, 1);
  lcd.print("Relay ");
  lcd.print(selectedRelay + 1);

  while (digitalRead(setButton4)) {
    if (digitalRead(setButton2) == LOW) {
      selectedRelay = (selectedRelay + 1) % 4;
      delay(debounce);
    }
    if (digitalRead(setButton3) == LOW) {
      selectedRelay = (selectedRelay + 3) % 4;
      delay(debounce);
    }
    lcd.setCursor(0, 1);
    lcd.print("Relay ");
    lcd.print(selectedRelay + 1);
    lcd.print(" ");
  }

  menu = 8;
  delay(debounce);
}
void IncrementTime() {
  if (timerSetting == ON_HOUR) {
    if (onHour == 23) {
      onHour = 0;
    } else {
      onHour++;
    }
  } else if (timerSetting == ON_MINUTE) {
    if (onMinute == 59) {
      onMinute = 0;
    } else {
      onMinute++;
    }
  } else if (timerSetting == OFF_HOUR) {
    if (offHour == 23) {
      offHour = 0;
    } else {
      offHour++;
    }
  } else if (timerSetting == OFF_MINUTE) {
    if (offMinute == 59) {
      offMinute = 0;
    } else {
      offMinute++;
    }
  }
}

void DecrementTime() {
  if (timerSetting == ON_HOUR) {
    if (onHour == 0) {
      onHour = 23;
    } else {
      onHour--;
    }
  } else if (timerSetting == ON_MINUTE) {
    if (onMinute == 0) {
      onMinute = 59;
    } else {
      onMinute--;
    }
  } else if (timerSetting == OFF_HOUR) {
    if (offHour == 0) {
      offHour = 23;
    } else {
      offHour--;
    }
  } else if (timerSetting == OFF_MINUTE) {
    if (offMinute == 0) {
      offMinute = 59;
    } else {
      offMinute--;
    }
  }
}
void SwitchSetting() {
  if (timerSetting == ON_HOUR) {
    timerSetting = ON_MINUTE;
  } else if (timerSetting == ON_MINUTE) {
    timerSetting = OFF_HOUR;
  } else if (timerSetting == OFF_HOUR) {
    timerSetting = OFF_MINUTE;
  } else if (timerSetting == OFF_MINUTE) {
    timerSetting = ON_HOUR;
  }
}
void AdjustTimer() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Set Timer (Relay ");
  lcd.print(selectedRelay + 1);
  lcd.print("):");

  lcd.setCursor(0, 1);

  bool adjustOnTime = true; 

  while (digitalRead(setButton4)) {
    

    if (timerSetting == ON_HOUR) {
      bool timerEnabled = true;
      lcd.setCursor(0, 1);
      lcd.print(cursorChar);
      lcd.print("On: Hour ");
      PrintTwoDigits(onHour);
      lcd.print(":");
      PrintTwoDigits(onMinute);
    } else if (timerSetting == ON_MINUTE) {
    lcd.setCursor(0, 1);
      lcd.print("On: Hour ");
      PrintTwoDigits(onHour);
      lcd.print(":");
      lcd.print(cursorChar);
      PrintTwoDigits(onMinute);
    } else if (timerSetting == OFF_HOUR) {
      lcd.setCursor(0,2);
      lcd.print("  Off: Hour ");
      PrintTwoDigits(offHour);
      lcd.print(":");
      PrintTwoDigits(offMinute);
    } else if (timerSetting == OFF_MINUTE) {
      lcd.setCursor(0,2);
      lcd.print("  Off: Hour ");
      PrintTwoDigits(offHour);
      lcd.print(":");
      lcd.print(cursorChar);
      PrintTwoDigits(offMinute);
    }

    if (digitalRead(setButton2)==LOW) {
      IncrementTime();
      delay(debounce);
    }

    if (digitalRead(setButton3)==LOW) {
      DecrementTime();
      delay(debounce);
    }

    if (digitalRead(setButton1)==LOW) {
      SwitchSetting();
      delay(debounce);
    }
  }
  lcd.clear();
  menu = 0;
  delay(debounce);
}

void DisplayDateTime ()
{
//curreent date and time
  lcd.setCursor(0, 2);
  lcd.print("LED1 ");
  lcd.setCursor(0, 3);
  lcd.print("LED2 ");
  lcd.setCursor(9, 2);
  lcd.print("LED3 ");
  lcd.setCursor(9, 3);
  lcd.print("LED4 ");

  if(recv_pin.decode()){
    String response = String(recv_pin.decodedIRData.command);

    if(response == "48") { // NUM 1 BUTTON
      led1State = !led1State;
      digitalWrite(relay1, led1State ? HIGH : LOW);
      lcd.setCursor(5, 2);
      lcd.print(led1State ? "ON " : "OFF");
    }

    if(response == "24") { //NUM 2 BUTTON
      led2State = !led2State;  
      digitalWrite(relay2, led2State ? HIGH : LOW);
      lcd.setCursor(5, 3);
      lcd.print(led2State ? "ON " : "OFF");
    }

    if(response == "122"){ // NUM 3 BUTTON
      led3State = !led3State; 
      digitalWrite(relay3, led3State ? HIGH : LOW);
      lcd.setCursor(14, 2);
      lcd.print(led3State ? "ON " : "OFF");
    }

    if(response == "16"){ // NUM 4 BUTTON
      led4State = !led4State; 
      digitalWrite(relay4, led4State ? HIGH : LOW);
      lcd.setCursor(14, 3);
      lcd.print(led4State ? "ON " : "OFF");
    }

    if(response == "162"){ // POWER OFF BUTTON
      turnOffAllLEDs();
    }

    if(response == "34"){ // TEST BUTTON
      testAllLEDs();
    }

    recv_pin.resume();
  }
  
  checkPushButton(pushbutton1, 0);
  checkPushButton(pushbutton2, 1);
  checkPushButton(pushbutton3, 2);
  checkPushButton(pushbutton4, 3);

  DateTime now = rtc.now();
  if(digitalRead(setButton1)==LOW){
   menu=1;
   delay(debounce);
  }
  if(digitalRead(setButton4)==LOW){
    menu=7;
  }
  lcd.setCursor(0, 1);
  lcd.print("Hour:");
  if (now.hour()<=9)
  {
    lcd.print("0");
  }
  lcd.print(now.hour(), DEC);
  hourupg=now.hour();
  lcd.print(":");
  if (now.minute()<=9)
  {
    lcd.print("0");
  }
  lcd.print(now.minute(), DEC);
  minupg=now.minute();
  lcd.print(":");
  if(digitalRead(setButton1)==LOW){
   menu=1;
   delay(debounce);
  }
  if (now.second()<=9)
  {
    lcd.print("0");
  }
  lcd.print(now.second(), DEC);

  lcd.setCursor(0, 0);
  lcd.print("Date: ");
  if (now.day()<=9)
  {
    lcd.print("0");
  }
  lcd.print(now.day(), DEC);
  dayupg=now.day();
  lcd.print("/");
  if(digitalRead(setButton1)==LOW){
   menu=1;
   delay(debounce);
  }
  if (now.month()<=9)
  {
    lcd.print("0");
  }
  lcd.print(now.month(), DEC);
  monthupg=now.month();
  lcd.print("/");
  lcd.print(now.year(), DEC);
  yearupg=now.year();

if(digitalRead(setButton1)==LOW){
   menu=1;
   delay(debounce);
}
}

void DisplaySetHour()
{
// time setting
  settingTime = true;
  lcd.clear();
  DateTime now = rtc.now();
  
  lcd.setCursor(0,0);
  lcd.print("Set Hour:");
  lcd.setCursor(0,1);
  lcd.print(hourupg,DEC);
 
  while(digitalRead(setButton1)){
    delay(500);
  if(digitalRead(setButton2)==LOW)
  {
    if(hourupg==23)
    {
      hourupg=0;
    }
    else
    {
      hourupg=hourupg+1;
    }
    delay(debounce);
  
  }
   if(digitalRead(setButton3)==LOW)
  {
    if(hourupg==0)
    {
      hourupg=23;
    }
    else
    {
      hourupg=hourupg-1;
    }
    delay(debounce);
  }
  DateTime now = rtc.now();
  lcd.setCursor(0,0);
  lcd.print("Set Hour:");
  lcd.setCursor(0,1);
  lcd.print(hourupg,DEC);
  lcd.print(" ");
  }
     menu=2;
     delay(debounce);
}

void DisplaySetMinute()
{
// Setting  minutes

  lcd.clear();
  settingTime = true;
  lcd.setCursor(0,0);
  lcd.print("Set Minutes:");
  lcd.setCursor(0,1);
  lcd.print(minupg,DEC);


  while(digitalRead(setButton1)){
    if(digitalRead(setButton2)==LOW)
    {
      if (minupg==59)
      {
        minupg=0;
      }
      else
      {
        minupg=minupg+1;
      }
      delay(debounce);
    }
     if(digitalRead(setButton3)==LOW)
    {
      if (minupg==0)
      {
        minupg=59;
      }
      else
      {
        minupg=minupg-1;
      }
      delay(debounce);
    }
  lcd.setCursor(0,0);
  lcd.print("Set Minutes:");
  lcd.setCursor(0,1);
  lcd.print(minupg,DEC);
  lcd.print(" ");
  //delay(200);
  }
  menu=3;
  delay(debounce);
}
  
void DisplaySetYear()
{
// setting the year
  settingTime = true;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Set Year:");
  lcd.setCursor(0,1);
  lcd.print(yearupg,DEC);

  while(digitalRead(setButton1)){
    if(digitalRead(setButton2)==LOW)
    {    
      yearupg=yearupg+1;
    }
     if(digitalRead(setButton3)==LOW)
    {
      yearupg=yearupg-1;
    }
    delay(debounce);
    lcd.setCursor(0,0);
    lcd.print("Set Year:");
    lcd.setCursor(0,1);
    lcd.print(yearupg,DEC);
    lcd.print(" ");
  }
     menu=4;
     delay(debounce);
}

void DisplaySetMonth()
{
// Setting month
  settingTime = true;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Set Month:");
  lcd.setCursor(0,1);
  lcd.print(monthupg,DEC);
  while(digitalRead(setButton1)){
    if(digitalRead(setButton2)==LOW)
    {
      if (monthupg==12)
      {
        monthupg=1;
      }
      else
      {
        monthupg=monthupg+1;
      }
    }
     if(digitalRead(setButton3)==LOW)
    {
      if (monthupg==1)
      {
        monthupg=12;
      }
      else
      {
        monthupg=monthupg-1;
      }
    }
  
  lcd.setCursor(0,0);
  lcd.print("Set Month:");
  lcd.setCursor(0,1);
  lcd.print(monthupg,DEC);
  lcd.print(" ");
  delay(debounce);
  }
     menu=5;
     delay(debounce);
     //delay(200);
}

void DisplaySetDay()
{
// Setting the day
  settingTime = true;
  lcd.clear();
  delay(debounce);
  while(digitalRead(setButton1)){
    
    if(digitalRead(setButton2)==LOW)
    {
      if (dayupg==31)
      {
        dayupg=1;
      }
      else
      {
        dayupg=dayupg+1;
      }
    }
     if(digitalRead(setButton3)==LOW)
    {
      if (dayupg==1)
      {
        dayupg=31;
      }
      else
      {
        dayupg=dayupg-1;
      }
    }
    lcd.setCursor(0,0);
    lcd.print("Set Day:");
    lcd.setCursor(0,1);
    lcd.print(dayupg,DEC);
    lcd.print(" ");
    delay(debounce);
  }
     menu=6;
     delay(debounce);
}

void StoreAgg()
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("SAVING IN");
  lcd.setCursor(0,1);
  lcd.print("PROGRESS");
  rtc.adjust(DateTime(yearupg,monthupg,dayupg,hourupg,minupg,0));
  delay(200);
}


void StoreTimer() {
 

  int relayPin = relayPins[selectedRelay];

  


    DateTime now = rtc.now();

    if (now.hour() == onHour && now.minute() == onMinute) {
      digitalWrite(relayPin, HIGH);
    } else if (now.hour() == offHour && now.minute() == offMinute) {
      digitalWrite(relayPin, LOW);
      
    }

  
}




void toggleLED(int ledIndex) {
  switch (ledIndex) {
    case 0:
      led1State = !led1State;
      digitalWrite(relay1, led1State ? HIGH : LOW);
      lcd.setCursor(5, 2);
      lcd.print(led1State ? "ON " : "OFF");
      break;
    case 1:
      led2State = !led2State;
      digitalWrite(relay2, led2State ? HIGH : LOW);
      lcd.setCursor(5, 3);
      lcd.print(led2State ? "ON " : "OFF");
      break;
    case 2:
      led3State = !led3State;
      digitalWrite(relay3, led3State ? HIGH : LOW);
      lcd.setCursor(14, 2);
      lcd.print(led3State ? "ON " : "OFF");
      break;
    case 3:
      led4State = !led4State;
      digitalWrite(relay4, led4State ? HIGH : LOW);
      lcd.setCursor(14, 3);
      lcd.print(led4State ? "ON " : "OFF");
      break;
  }
}

void turnOffAllLEDs() {
  led1State = false;
  led2State = false;
  led3State = false;
  led4State = false;

  digitalWrite(relay1, LOW);
  digitalWrite(relay2, LOW);
  digitalWrite(relay3, LOW);
  digitalWrite(relay4, LOW);

  lcd.setCursor(5,2);
  lcd.print("OFF");
  lcd.setCursor(5,3);
  lcd.print("OFF");
  lcd.setCursor(14,2);
  lcd.print("OFF");
  lcd.setCursor(14,3);
  lcd.print("OFF");
}

void testAllLEDs() {
  led1State = !led1State;
  led2State = !led2State;
  led3State = !led3State;
  led4State = !led4State;

  digitalWrite(relay1, led1State ? HIGH : LOW);
  digitalWrite(relay2, led2State ? HIGH : LOW);
  digitalWrite(relay3, led3State ? HIGH : LOW);
  digitalWrite(relay4, led4State ? HIGH : LOW);

  lcd.setCursor(5,2);
  lcd.print(led1State ? "ON " : "OFF");
  lcd.setCursor(5,3);
  lcd.print(led2State ? "ON " : "OFF");
  lcd.setCursor(14,2);
  lcd.print(led3State ? "ON " : "OFF");
  lcd.setCursor(14,3);
  lcd.print(led4State ? "ON " : "OFF");
}
$abcdeabcde151015202530fghijfghij
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
GND5VSDASCLSQWRTCDS1307+