import sys
import json
import platform
import os
import subprocess

def get_screen_resolution():
    if os.environ.get('WAYLAND_DISPLAY'):
        try:
            res = subprocess.run(["grim", "-t", "ppm", "-"], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, timeout=1.0)
            if res.returncode == 0 and res.stdout:
                lines = res.stdout.split(b"\n", 3)
                if len(lines) >= 3 and lines[0].startswith(b"P6"):
                    dims = lines[1].strip().split(b" ")
                    if len(dims) == 2:
                        return int(dims[0]), int(dims[1])
        except Exception:
            pass

    try:
        import mss
        with mss.MSS() as sct:
            if len(sct.monitors) > 1:
                m = sct.monitors[1]
                return m["width"], m["height"]
            elif len(sct.monitors) > 0:
                m = sct.monitors[0]
                return m["width"], m["height"]
    except Exception:
        pass

    try:
        import tkinter as tk
        root = tk.Tk()
        root.withdraw()
        w, h = root.winfo_screenwidth(), root.winfo_screenheight()
        root.destroy()
        if w > 0 and h > 0:
            return w, h
    except Exception:
        pass

    try:
        res = subprocess.run(["xrandr"], capture_output=True, text=True)
        for line in res.stdout.split("\n"):
            if "*" in line:
                parts = line.split()[0].split("x")
                return int(parts[0]), int(parts[1])
    except Exception:
        pass

    return 1920, 1080

def probe_hardware():
    sw, sh = get_screen_resolution()
    capabilities = {
        "os": platform.system(),
        "display_server": None,
        "screen_width": sw,
        "screen_height": sh,
        "usb_devices": [],
        "serial_ports": [],
        "mapped_dofs": []
    }

    # 1. Probe OS level input/output capabilities
    if platform.system() == "Linux":
        if os.environ.get("WAYLAND_DISPLAY"):
            capabilities["display_server"] = "wayland"
        elif os.environ.get("DISPLAY"):
            capabilities["display_server"] = "x11"
        
        # If we have a display server, we have basic screen coordinates and keyboard DoFs
        if capabilities["display_server"]:
            capabilities["mapped_dofs"].extend(["os_mouse_x", "os_mouse_y", "os_mouse_click", "os_mouse_scroll", "os_keyboard"])

    elif platform.system() == "Windows" or platform.system() == "Darwin":
        capabilities["mapped_dofs"].extend(["os_mouse_x", "os_mouse_y", "os_mouse_click", "os_mouse_scroll", "os_keyboard"])

    # Always assume we can use the vocal tract driver (10 DoFs)
    capabilities["mapped_dofs"].extend([
        "vocal_pitch", "vocal_volume",
        "vocal_formant_1", "vocal_formant_2", "vocal_formant_3", "vocal_formant_4", "vocal_formant_5", "vocal_formant_6", "vocal_formant_7",
        "vocal_noise"
    ])

    # 2. Try to probe serial ports (e.g., Arduino with servos, robotic chassis)
    try:
        import serial.tools.list_ports
        ports = list(serial.tools.list_ports.comports())
        for p in ports:
            capabilities["serial_ports"].append(p.device)
            # If we detect a generic serial port, we tentatively map generic servos DoFs
            capabilities["mapped_dofs"].extend([f"serial_servo_{p.device}_1", f"serial_servo_{p.device}_2"])
    except Exception:
        pass # pyserial not installed or permission denied

    # 3. Try to probe USB devices (e.g. webcams, specific robots like Anki Vector)
    try:
        if platform.system() == "Linux" or platform.system() == "Darwin":
            result = subprocess.run(['lsusb'], capture_output=True, text=True)
            if result.returncode == 0:
                for line in result.stdout.split('\n'):
                    if line.strip():
                        capabilities["usb_devices"].append(line.strip())
                        # Example: Dynamic mapping for specific known USB signatures
                        if "Anki" in line or "Vector" in line:
                            capabilities["mapped_dofs"].extend(["vector_wheels_l", "vector_wheels_r", "vector_head_pitch", "vector_lift"])
    except Exception:
        pass

    # 4. Probe Power Supply (Battery / AC Power) in HAL
    power_info = {"is_ac": True, "battery_pct": None}
    try:
        if platform.system() == "Linux":
            if os.path.exists("/sys/class/power_supply/AC/online"):
                with open("/sys/class/power_supply/AC/online", "r") as f:
                    power_info["is_ac"] = (f.read().strip() == "1")
            if os.path.exists("/sys/class/power_supply/BAT0/capacity"):
                with open("/sys/class/power_supply/BAT0/capacity", "r") as f:
                    power_info["battery_pct"] = float(f.read().strip())
        elif platform.system() == "Darwin":
            res = subprocess.run(["pmset", "-g", "batt"], capture_output=True, text=True)
            if res.returncode == 0:
                power_info["is_ac"] = "AC Power" in res.stdout
    except Exception:
        pass
    capabilities["power"] = power_info

    # Ensure uniqueness of DoFs
    capabilities["mapped_dofs"] = list(set(capabilities["mapped_dofs"]))

    print(json.dumps({"status": "ready", "capabilities": capabilities}))

if __name__ == "__main__":
    probe_hardware()
