# LIVE CLOCK + DATE TEST
# For your Desk Buddy first section

import network
import urequests
import utime
from e_ink_library import EPD_2in7_V2
import framebuf
from logo import youtube_logo
from cal_logo import calender_logo
import uasyncio as asyncio


# =====================================
# WIFI
# =====================================
SSID = "YOUR WIFI NAME"
PASSWORD = " YOUR WIFI PASSWORD"
API_KEY = "YOUR API KEY"
CITY = "cityname"

URL = "http://api.openweathermap.org/data/2.5/weather?q={}&appid={}&units=metric".format(
    CITY, API_KEY
)

GCAL_URL = "YOUR GOOGLE SCRIPT API"

def fetch_calendar():

    global CAL_LINES

    try:
        import gc
        gc.collect()

        r = urequests.get(GCAL_URL)
        txt = r.text
        r.close()

        CAL_LINES = txt.split("\n")

        print("Calendar Updated")

    except Exception as e:

        print("Calendar Error:", e)
        CAL_LINES = ["TODAY", "No Events"]
        
def fetch_aqi():

    global AQI, AQI_TXT

    try:

        url = "http://api.openweathermap.org/data/2.5/air_pollution?lat={}&lon={}&appid={}".format(
            "28.64", "77.21", API_KEY
        )

        r = urequests.get(url)
        data = r.json()
        r.close()

        level = data["list"][0]["main"]["aqi"]

        AQI = str(level)

        if level == 1:
            AQI_TXT = "Good"

        elif level == 2:
            AQI_TXT = "Fair"

        elif level == 3:
            AQI_TXT = "Moder."

        elif level == 4:
            AQI_TXT = "Poor"

        else:
            AQI_TXT = "Bad"

        print("AQI Updated")

    except Exception as e:

        print("AQI Error:", e)

        AQI = "--"
        AQI_TXT = "--"
        
def fetch_weather():

    global TEMP, HUM, DESC, TZ_OFFSET

    try:

        r = urequests.get(URL)
        data = r.json()
        r.close()

        TEMP = str(int(data["main"]["temp"]))
        HUM  = str(data["main"]["humidity"]) + "%"
        DESC = data["weather"][0]["description"]

        TZ_OFFSET = data["timezone"]   # seconds

        print("Weather Updated")

    except Exception as e:

        print("Weather Error:", e)

        TEMP = "--"
        HUM  = "--"
        DESC = "Error"
        TZ_OFFSET = 19800

def get_time_date():

    t = utime.localtime()

    hour   = t[3]
    minute = t[4]
    day    = t[2]
    month  = t[1]
    wd     = t[6]

    days = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]
    months = ["Jan","Feb","Mar","Apr","May","Jun",
              "Jul","Aug","Sep","Oct","Nov","Dec"]

    ampm = "AM"

    if hour >= 12:
        ampm = "PM"

    hour = hour % 12
    if hour == 0:
        hour = 12

    TIME_TXT = "%02d:%02d" % (hour, minute)

    DATE_TXT = "%s, %02d %s" % (
        days[wd],
        day,
        months[month - 1]
    )

    return TIME_TXT, ampm, DATE_TXT

def connect_wifi():

    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(SSID, PASSWORD)

    print("Connecting WiFi...")

    while not wlan.isconnected():
        time.sleep(1)

    print("WiFi Connected")



def draw_degree(fb, x, y):
    # small 4x4 hollow circle
    fb.pixel(x+1, y, 0)
    fb.pixel(x+2, y, 0)

    fb.pixel(x, y+1, 0)
    fb.pixel(x+3, y+1, 0)

    fb.pixel(x, y+2, 0)
    fb.pixel(x+3, y+2, 0)

    fb.pixel(x+1, y+3, 0)
    fb.pixel(x+2, y+3, 0)
    
def draw_bmp(fb, bmp, x0, y0, w, h, invert=True):
    bytes_per_row = w // 8
    for y in range(h):
        for x in range(w):
            byte_index = y * bytes_per_row + (x // 8)
            bit = bmp[byte_index] & (128 >> (x % 8))
            if invert:
                if not bit:
                    fb.pixel(x0 + x, y0 + y, 0)
            else:
                if bit:
                    fb.pixel(x0 + x, y0 + y, 0)

def big_text(fb, txt, x, y, scale=3):

    for i, ch in enumerate(txt):

        # draw character to temp buffer
        buf = bytearray(8 * 8 // 8)
        temp = framebuf.FrameBuffer(buf, 8, 8, framebuf.MONO_HLSB)
        temp.fill(0)
        temp.text(ch, 0, 0, 1)

        # scale pixels
        for yy in range(8):
            for xx in range(8):
                if temp.pixel(xx, yy):
                    fb.fill_rect(
                        x + i*8*scale + xx*scale,
                        y + yy*scale,
                        scale,
                        scale,
                        0
                    )

def round_rect(fb, x, y, w, h, r=8, t=2, color=0):

    for k in range(t):

        rr = r - k

        # straight lines
        fb.hline(x + rr, y + k, w - 2*rr, color)
        fb.hline(x + rr, y + h - 1 - k, w - 2*rr, color)

        fb.vline(x + k, y + rr, h - 2*rr, color)
        fb.vline(x + w - 1 - k, y + rr, h - 2*rr, color)

        # quarter-circle corners
        for i in range(rr):

            yy = int((rr*rr - i*i) ** 0.5)

            # top-left
            fb.pixel(x + rr - i, y + rr - yy, color)

            # top-right
            fb.pixel(x + w - rr - 1 + i, y + rr - yy, color)

            # bottom-left
            fb.pixel(x + rr - i, y + h - rr - 1 + yy, color)

            # bottom-right
            fb.pixel(x + w - rr - 1 + i, y + h - rr - 1 + yy, color)



# =====================================
# MAIN
# =====================================
if __name__ == '__main__':

    # -------------------------
    # connect wifi first
    # -------------------------
    import time
    # -------------------------
    # init display
    # -------------------------
   # time.sleep(5)
    epd = EPD_2in7_V2()
    time.sleep(3)

    epd.set_rotation("landscape")

    fb = epd.imageblack
    fb.fill(1)
    time.sleep(2)
    connect_wifi()

    # -------------------------
    # fetch weather + timezone
    # -------------------------
    fetch_weather()
    fetch_aqi()
    fetch_calendar()
    time.sleep(3)
    # -------------------------
    # draw static panels
    # -------------------------
    round_rect(fb, 6, 6, 120, 75, 6)
    round_rect(fb, 6, 88, 120, 82, 6)
    round_rect(fb, 130, 6, 130, 164, 6)

    # -------------------------
    # first draw clock
    # -------------------------
    TIME_TXT, AMPM, DATE_TXT = get_time_date()

    big_text(fb, TIME_TXT, 16, 20, 2)
    fb.text(AMPM, 100, 26, 0)
    fb.text("Desk Buddy", 22, 45, 0)
    fb.text(DATE_TXT, 20, 62, 0)

    # -------------------------
    # weather section
    # -------------------------
    draw_bmp(fb, youtube_logo, 15, 95, 24, 24)

    big_text(fb, TEMP, 50, 102, 2)
    draw_degree(fb, 83, 102)
    big_text(fb, "C", 88, 102, 2)

    fb.text(DESC, 12, 128, 0)
    fb.text("Hum: " + HUM, 12, 143, 0)
    #fb.text("AQI: 92 Mod.", 12, 157, 0)
    fb.text("AQI: " + AQI + " " + AQI_TXT, 12, 157, 0)
    
   # calendar icon fixed at requested position
    draw_bmp(fb, calender_logo, 137, 12, 24, 24)

    y = 16

    for line in CAL_LINES:

        # section titles
        if line == "TODAY":

            fb.text("TODAY", 168, y, 0)
            y += 30          # extra space below icon/header

        elif line == "TOMORROW":

            y += 6
            fb.text("TOMORROW", 148, y, 0)
            y += 22

        # events
        else:

            fb.text(line[:16], 136, y, 0)
            y += 22
    # -------------------------
    # full refresh once
    # -------------------------
    epd.display()
    time.sleep(3)
    # -------------------------
    # live loop
    # -------------------------
    last_min = -1
    weather_timer = utime.time()

    while True:

        # ---------- update clock each minute ----------
        TIME_TXT, AMPM, DATE_TXT = get_time_date()

        now = utime.localtime()
        minute = now[4]

        if minute != last_min:

            last_min = minute

            # clear clock box inner area
            fb.fill_rect(12, 18, 108, 52, 1)

            big_text(fb, TIME_TXT, 16, 20, 2)
            fb.text(AMPM, 100, 26, 0)
            fb.text("Desk Buddy", 22, 45, 0)
            fb.text(DATE_TXT, 20, 62, 0)

            epd.display_partial()

        # ---------- weather refresh every 15 mins ----------
        if utime.time() - weather_timer > 900:

            weather_timer = utime.time()

            fetch_weather()
            fetch_aqi()
            fb.fill_rect(10, 92, 112, 72, 1)

            draw_bmp(fb, youtube_logo, 15, 95, 24, 24)

            big_text(fb, TEMP, 50, 102, 2)
            draw_degree(fb, 83, 102)
            big_text(fb, "C", 88, 102, 2)

            fb.text(DESC, 12, 128, 0)
            fb.text("Hum: " + HUM, 12, 143, 0)
           # fb.text("AQI: 92 Mod.", 12, 157, 0)
            fb.text("AQI: " + AQI + " " + AQI_TXT, 12, 157, 0)
            epd.display_partial()

       # utime.sleep(1)


