import dos

# Thin application wrappers; the shared UI engine owns widgets and rendering.
class Widget:
    def __init__(self, kind, parent, order):
        self.node = dos.intent("UI", "CREATE", kind, parent, order)
        dos.intent("UI", "SET_PALETTE", self.node, 4226, 6371, -1, 4327, 6479, 2047, 8452)

    def rect(self, x, y, width, height):
        dos.intent("UI", "SET_RECT", self.node, x, y, width, height)

    def text(self, value):
        dos.intent("UI", "SET_STRING", self.node, 1, value)

    def pressed(self, value):
        dos.intent("UI", "SET_INT", self.node, 16, int(value))

root = Widget(1, 0, 0)
header = Widget(1, root.node, 1)
heading = Widget(2, header.node, 1)
status = Widget(2, root.node, 2)
hint = Widget(2, root.node, 3)
button = Widget(3, root.node, 4)
dos.intent("UI", "SET_PALETTE", root.node, 4226, 4226, -1, -1, 6371, 2047, 8452)
heading.text("d/Python | Retained widgets")
status.text("Button clicks: 0")
hint.text("Click the button, or press Space / Enter.")
button.text("Add a click")
clicks = 0
pointer_down = False
armed = False

def layout(width, height):
    root.rect(0, 0, width, height)
    header.rect(12, 12, max(1, width - 24), 44)
    heading.rect(24, 26, max(1, width - 48), 20)
    status.rect(24, 82, max(1, width - 48), 22)
    hint.rect(24, 112, max(1, width - 48), 22)
    button.rect(24, 148, 144, 32)

def increment():
    global clicks
    clicks += 1
    status.text("Button clicks: " + str(clicks))
    dos.service("INVALIDATE")

@dos.on("WINDOW_OPEN")
def open_window():
    dos.service("SET_TITLE", "d/Python — Retained widgets")
    layout(dos.service("WIDTH"), dos.service("HEIGHT"))

@dos.on("WINDOW_DRAW")
def draw_window():
    # The application requests its complete scene; the engine owns damage work.
    dos.intent("UI", "SYNC", root.node)

@dos.on("WINDOW_RESIZE")
def resize_window(width, height):
    layout(width, height)
    dos.service("INVALIDATE")

@dos.on("ON_POINTER")
def on_pointer(x, y, buttons):
    global pointer_down, armed
    down = buttons % 2 == 1
    hit, detail = dos.intent("UI", "HIT_TEST", button.node, x, y)
    inside = hit == button.node
    if down and not pointer_down:
        armed = inside
    elif not down and pointer_down:
        if armed and inside:
            increment()
        armed = False
    button.pressed(armed and down and inside)
    pointer_down = down
    dos.service("INVALIDATE")

@dos.on("ON_KEY")
def on_key(key):
    if key == 32 or key == 13:
        increment()

@dos.on("WINDOW_CLOSE")
def close_window():
    dos.intent("UI", "DESTROY", root.node)
