#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = []
# ///

import json
import socket
import sys
import time

state, mode, text = sys.argv[1:4]
buttons = {
    "up": ("/machine/adc", "adci[2]", 2242, 4095),
    "down": ("/machine/adc", "adci[2]", 5, 4095),
    "left": ("/machine/adc", "adci[1]", 1493, 4095),
    "right": ("/machine/adc", "adci[1]", 5, 4095),
    "select": ("/machine/adc", "adci[1]", 2694, 4095),
}
rows = ["1234567890", "qwertyuiop", "asdfghjkl", "zxcvbnm"]
widths = [10, 10, 9, 9, 6 if mode == "url" else 5]
keys = {char: (row, col) for row, chars in enumerate(rows) for col, char in enumerate(chars)}
if mode == "url":
    keys.update({":": (4, 1), "/": (4, 2), ".": (4, 3)})
    ok = (4, 5)
else:
    ok = (4, 4)

sock = socket.socket(socket.AF_UNIX)
sock.connect(f"{state}/qmp.sock")
stream = sock.makefile("rw")
json.loads(stream.readline())

def command(execute, arguments=None):
    payload = {"execute": execute}
    if arguments is not None:
        payload["arguments"] = arguments
    stream.write(json.dumps(payload) + "\n")
    stream.flush()
    while True:
        response = json.loads(stream.readline())
        if "return" in response or "error" in response:
            if "error" in response:
                raise RuntimeError(response["error"])
            return

command("qmp_capabilities")

def press(name):
    path, prop, pressed, released = buttons[name]
    command("qom-set", {"path": path, "property": prop, "value": pressed})
    time.sleep(0.06)
    command("qom-set", {"path": path, "property": prop, "value": released})
    time.sleep(1 if name == "select" else 0.12)

row = col = 0

def move_to(target_row, target_col):
    global row, col
    while row:
        old_width = widths[row]
        press("up")
        row -= 1
        col = col * widths[row] // old_width
    while col:
        press("left")
        col -= 1
    while row < target_row:
        old_width = widths[row]
        press("down")
        row += 1
        col = col * widths[row] // old_width
    while col < target_col:
        press("right")
        col += 1

for char in text.lower():
    move_to(*keys[char])
    press("select")
move_to(*ok)
press("select")
