#include <Wire.h>
#include <LiquidCrystal.h>
#include <RTClib.h>
#include <Keypad.h>

RTC_DS1307 rtc;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const byte ROWS = 4;
const byte COLS = 4;

char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte pin_rows[ROWS] = {9, 8, 7, 6};
byte pin_column[COLS] = {13, A3, A2, A1};

Keypad keypad = Keypad(makeKeymap(keys), pin_rows, pin_column, ROWS, COLS);
const int buzzerPin = 10;
const int alarmTimeout = 10000;

bool alarmSet = false;
bool alarmTriggered = false;
int alarmHour = 0;
int alarmMinute = 0;
int alarmDay = 0;
int alarmMonth = 0;
int alarmYear = 0;
unsigned long alarmStartTime;

void setup() {
  lcd.begin(16, 2);
  lcd.print(" Alarm Clock");
  delay(2000);

  Wire.begin();
  rtc.begin();

  if (!rtc.isrunning()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  lcd.clear();
  lcd.print("Initializing...");

  delay(2000);
  lcd.clear();
}

void loop() {
  DateTime now = rtc.now();

  if (!alarmTriggered) {
    lcd.setCursor(0, 0);
    lcd.print(now.day(), DEC);
    lcd.print('/');
    lcd.print(now.month(), DEC);
    lcd.print('/');
    lcd.print(now.year(), DEC);

    lcd.setCursor(0, 1);
    lcd.print(now.hour(), DEC);
    lcd.print(':');
    lcd.print(now.minute(), DEC);
    lcd.print(':');
    lcd.print(now.second(), DEC);
  }

  if (alarmSet && !alarmTriggered && now.day() == alarmDay && now.month() == alarmMonth && now.year() == alarmYear && now.hour() == alarmHour && now.minute() == alarmMinute) {
    activateAlarm();
  }

  if (alarmTriggered && (millis() - alarmStartTime) >= alarmTimeout) {
    turnOffAlarm();
  }

  char key = keypad.getKey();
  if (key) {
    if (key == '#') {
      setAlarm();
    } else if (key == '*') {
      turnOffAlarm();
    } else {

    }
  }

  delay(500);
}

void setAlarm() {
  lcd.clear();
  lcd.print("Set Alarm:");
  lcd.setCursor(0, 1);
  lcd.print("DD/MM HH:MM");

  int day = 0;
  int month = 0;
  int hours = 0;
  int minutes = 0;

  int cursorPos = 0;

  while (true) {
    char key = keypad.getKey();
    if (key) {
      if (key >= '0' && key <= '9') {
        if (cursorPos == 0) {
          if (day < 10) {
            day = (day * 10) + (key - '0');
            lcd.setCursor(0, 1);
            lcd.print(day);
          }
        } else if (cursorPos == 1) {
          if (month < 10) {
            month = (month * 10) + (key - '0');
            lcd.setCursor(3, 1);
            lcd.print(month);
          }
        } else if (cursorPos == 2) {
          if (hours < 10) {
            hours = (hours * 10) + (key - '0');
            lcd.setCursor(6, 1);
            lcd.print(hours);
          }
        } else if (cursorPos == 3) {
          if (minutes < 10) {
            minutes = (minutes * 10) + (key - '0');
            lcd.setCursor(9, 1);
            lcd.print(minutes);
          }
        }
      } else if (key == '#') {
        if (cursorPos == 0) {
          cursorPos = 1;
        } else if (cursorPos == 1) {
          cursorPos = 2;
        } else if (cursorPos == 2) {
          cursorPos = 3;
        } else if (cursorPos == 3) {
          alarmDay = day;
          alarmMonth = month;
          alarmYear = rtc.now().year();
          alarmHour = hours;
          alarmMinute = minutes;
          lcd.clear();
          lcd.print("Alarm set!");
          delay(2000);
          break;
        }
      } else if (key == '*') {
        if (cursorPos > 0) {
          cursorPos--;
        }
      }
    }
  }
  alarmSet = true;
  alarmTriggered = false;
}

void turnOffAlarm() {
  lcd.clear();
  lcd.print("Alarm off");
  noTone(buzzerPin);
  alarmSet = false;
  alarmTriggered = false;
  delay(2000);
}

void activateAlarm() {
  lcd.clear();
  lcd.print("Alarm!");
  lcd.setCursor(0, 1);
  lcd.print("Wake up!");
  tone(buzzerPin, 1000);
  alarmStartTime = millis();
  alarmTriggered = true;
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
keypad:R1
keypad:R2
keypad:R3
keypad:R4
keypad:C1
keypad:C2
keypad:C3
keypad:C4
lcd:VSS
lcd:VDD
lcd:V0
lcd:RS
lcd:RW
lcd:E
lcd:D0
lcd:D1
lcd:D2
lcd:D3
lcd:D4
lcd:D5
lcd:D6
lcd:D7
lcd:A
lcd:K
GND5VSDASCLSQWRTCDS1307+
rtc1:GND
rtc1:5V
rtc1:SDA
rtc1:SCL
rtc1:SQW
bz1:1
bz1:2
r1:1
r1:2
pot1:GND
pot1:SIG
pot1:VCC