#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h> // Library untuk RTC DS3231 atau DS1307

RTC_DS3231 rtc; // Objek RTC DS3231

#define OLED_RESET 22
Adafruit_SSD1306 display(OLED_RESET);

LiquidCrystal_I2C lcd(0x27, 20, 4); // Address LCD2004 0x27, 20 characters x 4 lines

const int buttonPin = 14;
const int buzzerPin = 33;
bool buttonState = LOW; // State of the button
bool lastButtonState = LOW; // Previous state of the button
unsigned long lastDebounceTime = 0; // Last time the button state changed
unsigned long debounceDelay = 50; // Debounce time in milliseconds
int attendanceCount = 0;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP); // Enable internal pull-up resistor
  pinMode(buzzerPin, OUTPUT);

  Serial.begin(9600);

  // initialize with the I2C addr 0x3D (for the 128x64)
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;
  }

  // Initialize RTC
  rtc.begin();

  if (rtc.lostPower()) {
    rtc.adjust(DateTime(2024, 5, 4, 8, 0, 0)); // Set tanggal, bulan, tahun, jam, menit, dan detik sesuai waktu di Indonesia
}


  display.display(); // Display startup message
  delay(2000);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Welcome to Absensi");
  display.display();
  delay(2000);
  display.clearDisplay();

  lcd.init();        // Initialize LCD
  lcd.backlight();   // Turn on LCD backlight
  updateLCD();       // Update LCD display initially
}

void loop() {
  DateTime now = rtc.now(); // Get current time from RTC

  // Display real-time clock on OLED
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print(F("Time: "));
  display.print(now.year());
  display.print("-");
  display.print(now.month());
  display.print("-");
  display.print(now.day());
  display.print(" ");
  display.print(now.hour());
  display.print(":");
  if (now.minute() < 10) {
    display.print("0");
  }
  display.print(now.minute());
  display.print(":");
  if (now.second() < 10) {
    display.print("0");
  }
  display.println(now.second());
  display.display();

  int reading = digitalRead(buttonPin);

  if (reading != lastButtonState) {
    lastDebounceTime = millis(); // Reset debounce timer
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != buttonState) {
      buttonState = reading;

      if (buttonState == HIGH) {
        digitalWrite(buzzerPin, HIGH); // Turn on buzzer
        delay(1000);                   // Buzzer on time
        digitalWrite(buzzerPin, LOW);  // Turn off buzzer
        displayAttendance();           // Update OLED display
        attendanceCount++;            // Increment attendance count
        updateLCD();                  // Update LCD display
        delay(1000);                  // Delay to avoid multiple button presses
      }
    }
  }

  lastButtonState = reading;
}

void displayAttendance() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Attendance Successful!");
  display.display();
  delay(1000); // Delay for display message

  display.clearDisplay(); // Clear OLED display after delay
  display.display();
}

void updateLCD() {
  lcd.clear();           // Clear LCD display
  lcd.setCursor(2, 0);
  lcd.print("Attendance Count:");
  lcd.setCursor(10, 1);
  lcd.print(attendanceCount);
  lcd.setCursor(1, 3);
  lcd.print("Selamat Bekerja :)");
}

void setTimeFromSerial() {
  Serial.println(F("Please set the current time (YYYY-MM-DD HH:MM:SS):"));
  while (!Serial.available()) {
    // Wait for user input
  }

  String input = Serial.readStringUntil('\n');
  int year, month, day, hour, minute, second;
  if (sscanf(input.c_str(), "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second) == 6) {
    rtc.adjust(DateTime(year, month, day, hour, minute, second));
    Serial.println(F("Time set successfully!"));
  } else {
    Serial.println(F("Invalid input! Please enter time in the format YYYY-MM-DD HH:MM:SS"));
    setTimeFromSerial(); // Re-prompt user to set time
  }
}