#!/usr/bin/env python3
"""Pi HDMI mode for DyzineFrame display_mode (labwc + kanshi).

Mini panels advertise preferred 1920x360 but Pi OS / stock kanshi often force
1920x1080. DF then draws a 360-tall framebuffer into the top third of a 1080
mode — looks squished on a real 1920x360 strip.
"""

from __future__ import annotations

import os
import subprocess
from pathlib import Path

APP_ROOT = Path(__file__).resolve().parent
KANSHI_CONFIG = Path.home() / ".config" / "kanshi" / "config"


def _display_mode() -> str:
    cfg = APP_ROOT / "config.ini"
    try:
        text = cfg.read_text(encoding="utf-8", errors="replace")
    except OSError:
        return "TBX"
    for line in text.splitlines():
        s = line.split(";", 1)[0].strip()
        if s.lower().startswith("display_mode"):
            parts = s.split("=", 1)
            if len(parts) == 2:
                mode = parts[1].strip().upper() or "TBX"
                if mode == "STRIP":
                    return "MINI"
                return mode
    return "TBX"


def _wayland_env() -> dict[str, str] | None:
    env = os.environ.copy()
    runtime = env.get("XDG_RUNTIME_DIR") or f"/run/user/{os.getuid()}"
    env["XDG_RUNTIME_DIR"] = runtime
    if env.get("WAYLAND_DISPLAY"):
        sock = Path(runtime) / env["WAYLAND_DISPLAY"]
        if sock.exists() or Path(str(sock) + ".lock").exists():
            return env
    for name in ("wayland-0", "wayland-1"):
        if (Path(runtime) / name).exists():
            env["WAYLAND_DISPLAY"] = name
            return env
    return None


def _mode_for_display(mode: str) -> str:
    if mode == "MINI":
        return "1920x360@60.000"
    # TBX / default desktop
    return "1920x1080@60.000"


def write_kanshi_profile(mode: str | None = None) -> Path:
    """Persist kanshi profile so labwc keeps the right mode after reboot."""
    mode = mode or _display_mode()
    hz_mode = _mode_for_display(mode)
    KANSHI_CONFIG.parent.mkdir(parents=True, exist_ok=True)
    body = (
        "profile {\n"
        f"\toutput HDMI-A-1 enable mode {hz_mode} "
        "position 0,0 transform normal\n"
        "}\n"
    )
    KANSHI_CONFIG.write_text(body, encoding="utf-8")
    return KANSHI_CONFIG


def apply_hdmi_mode(mode: str | None = None) -> bool:
    """Set current output via wlr-randr when a Wayland session is reachable."""
    mode = mode or _display_mode()
    env = _wayland_env()
    if env is None:
        print("pi_hdmi_mode: no Wayland session — kanshi only", flush=True)
        return False
    if mode == "MINI":
        candidates = ["1920x360@60.000000", "1920x360@60.000", "1920x360"]
    else:
        candidates = ["1920x1080@60.000000", "1920x1080@60.000", "1920x1080"]
    last_err = ""
    for cand in candidates:
        try:
            proc = subprocess.run(
                ["wlr-randr", "--output", "HDMI-A-1", "--mode", cand],
                env=env,
                capture_output=True,
                text=True,
                timeout=10,
                check=False,
            )
        except (OSError, subprocess.TimeoutExpired) as exc:
            last_err = str(exc)
            continue
        if proc.returncode == 0:
            print(f"pi_hdmi_mode: HDMI-A-1 -> {cand} ({mode})", flush=True)
            return True
        last_err = (proc.stderr or proc.stdout or "").strip()
    print(f"pi_hdmi_mode: wlr-randr failed ({last_err})", flush=True)
    return False


def ensure_hdmi_for_config() -> None:
    """Write kanshi + apply live mode from config.ini display_mode."""
    mode = _display_mode()
    path = write_kanshi_profile(mode)
    print(f"pi_hdmi_mode: wrote {path} for {mode}", flush=True)
    apply_hdmi_mode(mode)


if __name__ == "__main__":
    ensure_hdmi_for_config()
