print("Hello World!")

import time
import board
import microcontroller
import digitalio
import usb_hid

from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode

digit_pins = [board.P0_29, board.P0_31, board.P1_13, board.P1_15]
segment_pins = [
    board.P1_06, board.P1_04, board.P0_11, board.P1_00,
    board.P0_24, board.P0_22, board.P0_20, board.P0_17,
    board.P0_08, board.P0_06
]
kbd_col_pins = [board.P0_09, board.P0_10, board.P1_11]

#
# HELPERS
#

def pin_output(p: microcontroller.Pin) -> digitalio.DigitalInOut:
    p = digitalio.DigitalInOut(p)
    p.direction = digitalio.Direction.OUTPUT
    p.value = True  # inverted
    return p

def pin_input(p: microcontroller.Pin) -> digitalio.DigitalInOut:
    p = digitalio.DigitalInOut(p)
    p.direction = digitalio.Direction.INPUT
    p.pull = digitalio.Pull.DOWN
    return p

#
# CONFIGURE HARDWARE
#

digits = [pin_output(pin) for pin in digit_pins]
segments = [pin_output(pin) for pin in segment_pins]
kbd_cols = [pin_input(pin) for pin in kbd_col_pins]

FONT = {
    "0":[0,1,2,3,4,5],
    "1":[1,2],
    "2":[0,1,3,4,6],
    "3":[0,1,2,3,6],
    "4":[1,2,5,6],
    "5":[0,2,3,5,6],
    "6":[0,2,3,4,5,6],
    "7":[0,1,2],
    "8":[0,1,2,3,4,5,6],
    "9":[0,1,2,3,5,6],
    " ":[]
}

KEYCODES = {
       (6,2) : Keycode.C,             # COOK
       (5,2) : Keycode.D,             # DEFROST
       (4,0) : Keycode.R,             # REHEAT
       (3,1) : Keycode.W,             # WAVES
       (5,1) : Keycode.T,             # TIME
       (6,1) : Keycode.E,             # ELEMENTS
       (2,2) : Keycode.KEYPAD_PLUS,   # +
       (1,2) : Keycode.KEYPAD_MINUS,  # -
       (7,0) : Keycode.C,             # 10min
       (6,0) : Keycode.B,             # 1min
       (5,0) : Keycode.A,             # 10sec
       (7,1) : Keycode.ESCAPE,        # STOP
       (4,1) : Keycode.ENTER,         # START
}

def digit_on(i):  digits[i].value = False
def digit_off(i): digits[i].value = True

def seg_on(i):
    segments[i].value = (i >= 8)

def seg_off(i):
    segments[i].value = not (i >= 8)

def all_digits_off():
    for i in range(4):
        digit_off(i)

def all_segments_off():
    for i in range(len(segments)):
        seg_off(i)


def show_digit(pos, ch, colon=False):
    all_digits_off()
    all_segments_off()

    for s in FONT.get(ch, []):
        seg_on(s)

    if colon:
        seg_on(7)

    digit_on(pos)

KBD_ROWS = 8

def scan_keyboard():
    pressed = []
    all_digits_off()
    all_segments_off()

    for row in range(KBD_ROWS):
        seg_on(row)
        # time.sleep(0.00005)

        for col, pin in enumerate(kbd_cols):
            if not pin.value:
                pressed.append((row, col))
                # print(row,col)

        seg_off(row)

    return pressed

hid = usb_hid.devices[0]
kbd = Keyboard(usb_hid.devices)

CMD_KEY = 0x01
CMD_SET_TIME = 0x10
CMD_SET_TEXT = 0x12

forced_text = None
time_offset = 0

def send_key(row, col):
    report = bytearray(8)
    report[0] = CMD_KEY
    report[1] = row
    report[2] = col
    hid.send_report(report,report_id=1)
    code = KEYCODES.get((row,col),None)
    if code is not None:
        kbd.send(code)

def hid_poll():
    report = hid.get_last_received_report()
    if not report:
        return

    cmd = report[0]

    if cmd == CMD_SET_TIME:
        secs = int.from_bytes(report[1:5], "little")
        set_time_from_host(secs)

    elif cmd == CMD_SET_TEXT:
        set_forced_text(
            chr(report[1]),
            chr(report[2]),
            chr(report[3]),
            chr(report[4]),
        )

last_keys = set()

while True:
    now = int(time.monotonic() + time_offset)
    h = (now // 3600) % 24
    m = (now // 60) % 60
    s = now % 60

    text = forced_text if forced_text else f"{h:02d}{m:02d}"
    blink = (s % 2) == 0

    for i in range(4):
        show_digit(i, text[i], colon=(blink and i in (0,1)))
        # time.sleep(0.002)

    keys = set(scan_keyboard())
    for k in keys - last_keys:
        print('Test', *k)
        send_key(*k)
    last_keys = keys

    hid_poll()

###OLD
# led_raws = [board.P0_29,board.P0_31,board.P1_13,board.P1_15]
# led_kbd_cols = [board.P1_06, board.P1_04, board.P0_11, board.P1_00, board.P0_24, board.P0_22, board.P0_20, board.P0_17]
# kbd_cols_length = 8
# kbd_rows = [board.P0_09,board.P0_10,board.P1_11]
# km = keypad.KeyMatrix(
#     row_pins=kbd_rows,
#     column_pins=led_kbd_cols[:kbd_cols_length],
#     # columns_to_anodes=False
# )
#

#
# # Create an event we will reuse over and over.
# event = keypad.Event()
# while True:
#     if km.events.get_into(event):
#         print(event)
#         key_number = event.key_number
#         keycode = KEYCODES[key_number]
#         if keycode:
#             if event.pressed:
#                 kbd.press(keycode)
#             if event.released:
#                 kbd.release(keycode)
#

