#!/usr/bin/env python3
"""Renderiza el reactor a PNG sin arrancar Newelle.

Extrae el metodo _draw_reactor REAL de call.py (no una copia) y lo ejecuta
con un self falso y niveles de audio simulados. Sirve para iterar el diseño
sin pagar el build de flatpak cada vez.

    python3 preview_reactor.py [salida.png]
"""
import ast
import math
import sys
import textwrap
from pathlib import Path

import cairo

CALL_PY = Path(__file__).parent / "newelle" / "src" / "ui" / "widgets" / "call.py"
SIZE = 240


def load_draw_func():
    """Saca _draw_reactor del fuente y lo compila aislado."""
    tree = ast.parse(CALL_PY.read_text())
    for node in ast.walk(tree):
        if isinstance(node, ast.FunctionDef) and node.name == "_draw_reactor":
            src = textwrap.dedent(ast.get_source_segment(CALL_PY.read_text(), node))
            ns = {"math": math}
            exec(compile(src, "call.py", "exec"), ns)
            return ns["_draw_reactor"]
    raise SystemExit("no encuentro _draw_reactor en call.py")


class FakePanel:
    """El minimo que _draw_reactor toca de self."""

    def __init__(self, levels, phase, user=False, assistant=False):
        self.reactor_levels = levels
        self.reactor_phase = phase
        self.user_speaking = user
        self.assistant_speaking = assistant


def frame(draw, panel, path):
    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, SIZE, SIZE)
    cr = cairo.Context(surface)
    # fondo del modo llamada, para juzgar el contraste real
    cr.set_source_rgb(0.04, 0.09, 0.13)
    cr.paint()
    draw(panel, None, cr, SIZE, SIZE)
    surface.write_to_png(str(path))


def main():
    draw = load_draw_func()
    out = Path(sys.argv[1] if len(sys.argv) > 1 else "reactor.png")

    escenas = [
        ("reposo", FakePanel([0.04] * 12, 0.0)),
        ("escuchando", FakePanel(
            [0.25, 0.55, 0.85, 0.60, 0.35, 0.70, 0.95, 0.45, 0.30, 0.65, 0.50, 0.20],
            1.1, user=True)),
        ("respondiendo", FakePanel(
            [0.40, 0.30, 0.55, 0.45, 0.60, 0.35, 0.50, 0.40, 0.55, 0.30, 0.45, 0.35],
            2.4, assistant=True)),
    ]

    # tira horizontal con las tres escenas
    strip = cairo.ImageSurface(cairo.FORMAT_ARGB32, SIZE * 3, SIZE)
    scr = cairo.Context(strip)
    scr.set_source_rgb(0.04, 0.09, 0.13)
    scr.paint()

    for i, (nombre, panel) in enumerate(escenas):
        tmp = Path(f"/tmp/_reactor_{nombre}.png")
        frame(draw, panel, tmp)
        img = cairo.ImageSurface.create_from_png(str(tmp))
        scr.set_source_surface(img, i * SIZE, 0)
        scr.paint()
        tmp.unlink(missing_ok=True)

    strip.write_to_png(str(out))
    print(f"escrito {out}  ({SIZE * 3}x{SIZE}) — reposo | escuchando | respondiendo")


if __name__ == "__main__":
    main()
