"""
Script to set the RTC using an NTP server.
RPI needs to be connected to the internet (WIFI).
Requires ntplib and pytz:
sudo pip3 install ntplib pytz --break-system-packages

/usr/bin/python3 /var/www/moduleair_pro_4g/RTC/set_with_NTP.py

"""
import smbus2
import time
from datetime import datetime
import ntplib
import pytz  # For timezone handling

# DS3231 I2C address
DS3231_ADDR = 0x68

# Registers for DS3231
REG_TIME = 0x00

def bcd_to_dec(bcd):
    """Convert BCD to decimal."""
    return (bcd // 16 * 10) + (bcd % 16)

def dec_to_bcd(dec):
    """Convert decimal to BCD."""
    return (dec // 10 * 16) + (dec % 10)

def set_time(bus, year, month, day, hour, minute, second):
    """Set the RTC time."""
    # Convert the time to BCD format
    second_bcd = dec_to_bcd(second)
    minute_bcd = dec_to_bcd(minute)
    hour_bcd = dec_to_bcd(hour)
    day_bcd = dec_to_bcd(day)
    month_bcd = dec_to_bcd(month)
    year_bcd = dec_to_bcd(year - 2000)  # DS3231 uses year from 2000

    # Write time to DS3231
    bus.write_i2c_block_data(DS3231_ADDR, REG_TIME, [
        second_bcd,
        minute_bcd,
        hour_bcd,
        0x01,  # Day of the week (1=Monday, etc.)
        day_bcd,
        month_bcd,
        year_bcd
    ])

def read_time(bus):
    """Read the RTC time."""
    data = bus.read_i2c_block_data(DS3231_ADDR, REG_TIME, 7)
    second = bcd_to_dec(data[0] & 0x7F)
    minute = bcd_to_dec(data[1])
    hour = bcd_to_dec(data[2] & 0x3F)
    day = bcd_to_dec(data[4])
    month = bcd_to_dec(data[5])
    year = bcd_to_dec(data[6]) + 2000
    return (year, month, day, hour, minute, second)

def get_internet_time():
    """Get the current time from an NTP server."""
    ntp_client = ntplib.NTPClient()
    response = ntp_client.request('pool.ntp.org')
    utc_time = datetime.utcfromtimestamp(response.tx_time)
    return utc_time

def main():
    bus = smbus2.SMBus(1)

    # Get the current time from the RTC
    year, month, day, hours, minutes, seconds = read_time(bus)
    rtc_time = datetime(year, month, day, hours, minutes, seconds)

    # Get current UTC time from an NTP server
    try:
        internet_utc_time = get_internet_time()
        print(f"Time from Internet (UTC)     : {internet_utc_time.strftime('%Y-%m-%d %H:%M:%S')}")
    except Exception as e:
        print(f"Error retrieving time from the internet: {e}")
        return

    # Print current RTC time
    print(f"Actual RTC Time              : {rtc_time.strftime('%Y-%m-%d %H:%M:%S')}")

    # Set the RTC to UTC time
    set_time(bus, internet_utc_time.year, internet_utc_time.month, internet_utc_time.day, 
             internet_utc_time.hour, internet_utc_time.minute, internet_utc_time.second)

    # Read and print the new time from RTC
    year, month, day, hour, minute, second = read_time(bus)
    rtc_time_new = datetime(year, month, day, hour, minute, second)
    print(f"New RTC Time (UTC)           : {rtc_time_new.strftime('%Y-%m-%d %H:%M:%S')}")

if __name__ == "__main__":
    main()
