use esp_idf_hal::delay::FreeRtos;
use esp_idf_hal::gpio::*;
use esp_idf_hal::i2c::*;
use esp_idf_hal::peripherals::Peripherals;
use esp_idf_hal::prelude::*;
use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306};
use embedded_graphics::{
    mono_font::{ascii::FONT_6X10, MonoTextStyle},
    pixelcolor::BinaryColor,
    prelude::*,
    text::Text,
};
use rtc_rs::DS3231;

fn main() -> anyhow::Result<()> {
    // Initialize ESP32 peripherals
    let peripherals = Peripherals::take()?;
    let i2c = peripherals.i2c0;
    let sda = peripherals.pins.gpio21;
    let scl = peripherals.pins.gpio22;
    let buzzer = PinDriver::output(peripherals.pins.gpio12)?;
    let button_hour = PinDriver::input(peripherals.pins.gpio13)?;
    let button_minute = PinDriver::input(peripherals.pins.gpio14)?;
    let button_toggle = PinDriver::input(peripherals.pins.gpio15)?;

    // Configure I2C for RTC & OLED
    let config = I2cConfig::new().baudrate(100.kHz().into());
    let i2c = I2cDriver::new(i2c, sda, scl, &config)?;

    // Initialize OLED
    let interface = I2CDisplayInterface::new(i2c);
    let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
        .into_buffered_graphics_mode();
    display.init().unwrap();

    // Initialize RTC
    let mut rtc = DS3231::new(i2c);
    let mut alarm_hour = 12;
    let mut alarm_minute = 0;
    let mut alarm_enabled = false;
    let mut alarm_triggered = false;

    loop {
        // Read current time from RTC
        let time = rtc.get_time()?;

        // Handle button presses (with debouncing)
        if button_hour.is_low() {
            alarm_hour = (alarm_hour + 1) % 24;
            FreeRtos::delay_ms(200);
        }
        if button_minute.is_low() {
            alarm_minute = (alarm_minute + 1) % 60;
            FreeRtos::delay_ms(200);
        }
        if button_toggle.is_low() {
            alarm_enabled = !alarm_enabled;
            FreeRtos::delay_ms(200);
        }

        // Trigger alarm if conditions are met
        if alarm_enabled && time.hour == alarm_hour && time.minute == alarm_minute && !alarm_triggered {
            alarm_triggered = true;
            buzzer.set_high()?;
        }

        // Stop alarm after 1 minute
        if alarm_triggered && time.minute != alarm_minute {
            alarm_triggered = false;
            buzzer.set_low()?;
        }

        // Update OLED display
        display.clear(BinaryColor::Off)?;
        let text_style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On);

        // Display current time
        Text::new(
            &format!("{:02}:{:02}:{:02}", time.hour, time.minute, time.second),
            Point::new(10, 20),
            text_style,
        ).draw(&mut display)?;

        // Display alarm status
        Text::new(
            &format!("Alarm: {:02}:{:02} {}", alarm_hour, alarm_minute, if alarm_enabled { "ON" } else { "OFF" }),
            Point::new(10, 40),
            text_style,
        ).draw(&mut display)?;

        display.flush()?;
        FreeRtos::delay_ms(100);
    }
}
GND5VSDASCLSQWRTCDS1307+