# SPDX-FileCopyrightText: 2023 Frederick M Meyer
#
# SPDX-License-Identifier: MIT

import ipaddress
import ssl
import wifi
import socketpool
import adafruit_requests
import random
import os
import time
import rtc
import adafruit_ntp
import adafruit_datetime
import displayio
import framebufferio
import rgbmatrix
import board
import digitalio
import terminalio
import adafruit_display_text as adt
import adafruit_display_text.label as adtl

UTC_OFFSET = os.getenv('UTC_OFFSET')
TZ = os.getenv('TZ')

QUARTER = "Quarter"
HALF = "Half"
PAST = "Past"
UNTIL = "Until"
OCLOCK = "O'clock"
NOON = "Noon"
MIDNIGHT = "Midnight"
MINUTE = "Minute"
SINGLE_DIGITS = ["One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"]
TEN_PLUS = ["Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"]
TENS = ["Twenty", "Thirty", "Fourty", "Fifty"]

#time.sleep(15)

led = digitalio.DigitalInOut(board.LED)
led.direction = digitalio.Direction.OUTPUT
led.value = False

displayio.release_displays()

# Wifi details are in settings.toml file

print("My MAC addr:", [hex(i) for i in wifi.radio.mac_address])

print("Connecting to %s"%os.getenv("CIRCUITPY_WIFI_SSID"))
wifi.radio.connect(os.getenv("CIRCUITPY_WIFI_SSID"), os.getenv("CIRCUITPY_WIFI_PASSWORD"))
print("Connected to %s!"%os.getenv("CIRCUITPY_WIFI_SSID"))
print("My IP address is", wifi.radio.ipv4_address)

pool = socketpool.SocketPool(wifi.radio)

if UTC_OFFSET is None:
    requests = adafruit_requests.Session(pool, ssl.create_default_context())
    response = requests.get("http://worldtimeapi.org/api/timezone/" + TZ)
    response_as_json = response.json()
    UTC_OFFSET = response_as_json["raw_offset"] + response_as_json["dst_offset"]

ntp = adafruit_ntp.NTP(pool, server="us.pool.ntp.org", tz_offset=UTC_OFFSET // 3600)

rtc.RTC().datetime = ntp.datetime

last_minute_displayed = -1

def format_hour(hour_num):
    hour = hour_num % 24
    if hour == 0:
        o_hour = MIDNIGHT
    elif hour == 12:
        o_hour = NOON
    else:
        if hour > 12:
            hour -= 12
        elif hour == 0:
            hour = 12

        if hour < 10:
            o_hour = SINGLE_DIGITS[hour - 1]
        else:
            o_hour = TEN_PLUS[hour - 10]
    return hour, o_hour

COLOR_VALUES = [0, 128, 255]  # Brighter - Possible color values used for random 0..2 selection
#COLOR_VALUES = [0, 80, 160]   # Dimmer   - Possible color values used for random 0..2 selection
#COLOR_VALUES = [0, 64, 128]   # Dimmer   - Possible color values used for random 0..2 selection

def pick_random_color():
    # Pick a random color for each line and add it to the display
    r = COLOR_VALUES[random.randint(0, 2)]
    g = COLOR_VALUES[random.randint(0, 2)]
    b = COLOR_VALUES[random.randint(0, 2)]
    if not (r | g | b): r = g = b = COLOR_VALUES[2] # Set to white if black result

    return (r<<16|g<<8|b)

matrix = rgbmatrix.RGBMatrix(
    width=64, height=64, bit_depth=2,
    rgb_pins=[
        board.MTX_R1,
        board.MTX_G1,
        board.MTX_B1,
        board.MTX_R2,
        board.MTX_G2,
        board.MTX_B2
    ],
    addr_pins=[
        board.MTX_ADDRA,
        board.MTX_ADDRB,
        board.MTX_ADDRC,
        board.MTX_ADDRD,
        board.MTX_ADDRE
    ],
    clock_pin=board.MTX_CLK,
    latch_pin=board.MTX_LAT,
    output_enable_pin=board.MTX_OE
)

display = framebufferio.FramebufferDisplay(matrix, auto_refresh=True)
display.rotation = 0

while True:
    # time.struct_time(tm_year=2023, tm_mon=2, tm_mday=23, tm_hour=14, tm_min=6, tm_sec=29, tm_wday=3, tm_yday=54, tm_isdst=0)
    lt = time.localtime()

    hour = lt.tm_hour
    min = lt.tm_min

    #hour = 12  # For testing
    #min = 00   # For testing

    if last_minute_displayed != min:
        last_minute_displayed = min

        if min <= 30:
            o_min_half = "Past"
            hour, o_hour = format_hour(hour)
        else:
            o_min_half = "Until"
            min = 60 - min
            hour, o_hour = format_hour(hour + 1)

        if min == 15:
            o_min = "Quarter"
        elif min == 30:
            o_min = "Half"
        elif min == 0:
            o_min = ""
            o_min_half = ""
        elif min < 10:
            o_min = SINGLE_DIGITS[min - 1]
        elif min < 20:
            o_min = TEN_PLUS[min - 10]
        else:
            o_min = TENS[(min // 10) - 2]
            if min % 10:
                o_min += " " + SINGLE_DIGITS[(min % 10) - 1]

        if o_min not in [QUARTER, HALF, ""]:
            o_min += " " + MINUTE
            if min != 1: o_min += "s"

        if min > 0 or o_hour in [MIDNIGHT, NOON]:
            txt = (o_min + " " + o_min_half + " " + o_hour).strip()
        else:
            txt = (o_min + " " + o_min_half + " " + o_hour + " " + OCLOCK).strip()

        text_list = adt.wrap_text_to_pixels(txt, 60, font=terminalio.FONT)
        
        total_height = 0
        max_width = 0
        line_list = []
        for w in text_list:
            line = adtl.Label(
                terminalio.FONT,
                color=pick_random_color(),
                text=w,
                scale=1)
            line_list.append(line)
            zx, zy, zwidth, zheight = line.bounding_box
            total_height += zheight
            max_width = max(max_width, zwidth)
        xwork = ((60 - max_width) // 2) + 2
        ywork = ((60 - total_height) // 2) + 2 + 6

        current_y = ywork        
        g = displayio.Group()
        for l in line_list:
            l.x = xwork
            l.y = current_y
            zx, zy, zwidth, zheight = l.bounding_box
            current_y += zheight
            g.append(l)
        display.root_group=g

    time.sleep(1)