#!/usr/bin/env python3
import os
import subprocess
import sys
import dbus

BUS_NAME = "org.freedesktop.UPower.PowerProfiles"
OBJ_PATH = "/org/freedesktop/UPower/PowerProfiles"
IFACE = "org.freedesktop.UPower.PowerProfiles"
PROPS_IFACE = "org.freedesktop.DBus.Properties"


def get_bus_obj():
    bus = dbus.SystemBus()
    return bus.get_object(BUS_NAME, OBJ_PATH)


def cmd_launch(rest):
    profile = "performance"
    reason = "Requested via powerprofilesctl launch"
    app_id = "org.freedesktop.PowerProfiles.Launch"
    i = 0
    while i < len(rest):
        arg = rest[i]
        if arg == "--":
            i += 1
            break
        if arg in ("-p", "--profile") and i + 1 < len(rest):
            profile = rest[i + 1]
            i += 2
        elif arg.startswith("--profile="):
            profile = arg.split("=", 1)[1]
            i += 1
        elif arg in ("-r", "--reason") and i + 1 < len(rest):
            reason = rest[i + 1]
            i += 2
        elif arg.startswith("--reason="):
            reason = arg.split("=", 1)[1]
            i += 1
        elif arg in ("-i", "--appid") and i + 1 < len(rest):
            app_id = rest[i + 1]
            i += 2
        elif arg.startswith("--appid="):
            app_id = arg.split("=", 1)[1]
            i += 1
        else:
            break

    command = rest[i:]
    if not command:
        sys.exit("Usage: powerprofilesctl launch [-p PROFILE] [-r REASON] [-i APP_ID] [--] COMMAND [ARGS...]")

    obj = get_bus_obj()
    methods = dbus.Interface(obj, IFACE)
    cookie = methods.HoldProfile(profile, reason, app_id)
    try:
        rc = subprocess.call(command)
    finally:
        try:
            methods.ReleaseProfile(cookie)
        except Exception:
            pass
    sys.exit(rc)


def main():
    args = sys.argv[1:]
    cmd = args[0] if args else "list"

    if cmd in ("help", "--help", "-h"):
        print("Usage: powerprofilesctl [COMMAND]")
        print("\nCommands:")
        print("  list                     List available power profiles (default)")
        print("  get                      Print active power profile")
        print("  set <PROFILE>            Switch to power profile (power-saver, balanced, performance)")
        print("  launch [OPTS] COMMAND    Hold profile (default: performance) while running COMMAND")
        print("  version                  Print daemon version")
        return

    try:
        obj = get_bus_obj()
        props = dbus.Interface(obj, PROPS_IFACE)
    except Exception as e:
        sys.exit(f"Failed to connect to power-profiles daemon: {e}")

    if cmd == "get":
        print(props.Get(IFACE, "ActiveProfile"))
    elif cmd == "set":
        if len(args) < 2:
            sys.exit("Usage: powerprofilesctl set <profile>")
        try:
            props.Set(IFACE, "ActiveProfile", args[1])
        except dbus.exceptions.DBusException as e:
            sys.exit(f"Failed to set profile: {e.get_dbus_message()}")
    elif cmd in ("list", "status"):
        active = str(props.Get(IFACE, "ActiveProfile"))
        profiles = props.Get(IFACE, "Profiles")
        degraded = str(props.Get(IFACE, "PerformanceDegraded"))
        holds = props.Get(IFACE, "ActiveProfileHolds")
        for idx, p in enumerate(profiles):
            prof_name = str(p.get("Profile", ""))
            driver = str(p.get("Driver", ""))
            plat = str(p.get("PlatformDriver", ""))
            marker = "*" if prof_name == active else " "
            if idx > 0:
                print()
            print(f"{marker} {prof_name}:")
            if driver:
                print(f"    Driver:          {driver}")
            if plat:
                print(f"    Platform Driver: {plat}")
            if prof_name == "performance" and degraded:
                print(f"    Degraded:        yes ({degraded})")
        if holds:
            print("\nHolds:")
            for h in holds:
                print(f"  - {h.get('ApplicationId', '')}: {h.get('Profile', '')} ({h.get('Reason', '')})")
    elif cmd == "launch":
        cmd_launch(args[1:])
    elif cmd == "version":
        print(props.Get(IFACE, "Version"))
    else:
        sys.exit(f"Unknown command: '{cmd}'. Use 'powerprofilesctl help' for usage.")


if __name__ == "__main__":
    main()
