#!/usr/bin/env python3
"""ambilight-ctl — interfaccia a riga di comando per il demone ambilightd.

Parla con il demone via D-Bus e stampa JSON, cosi' il plasmoide puo' usarla
attraverso il DataSource "executable" di Plasma.

    ambilight-ctl state                 # JSON con tutto lo stato
    ambilight-ctl start | stop | toggle
    ambilight-ctl set brightness 0.8    # brightness|contrast|saturation|band|reverse|leds
    ambilight-ctl get contrast
"""
import json
import sys

BUS_NAME = "org.enne2.Ambilight"
OBJ_PATH = "/org/enne2/Ambilight"
IFACE = "org.enne2.Ambilight"

FALLBACK = {"daemon": False, "running": False, "brightness": 1.0, "contrast": 1.0,
            "saturation": 1.0, "band": 0.12, "reverse": True, "leds": 47, "fps": 0.0,
            "error": "demone non raggiungibile"}


def proxy():
    from gi.repository import Gio, GLib
    return Gio.DBusProxy.new_for_bus_sync(
        Gio.BusType.SESSION, Gio.DBusProxyFlags.NONE, None,
        BUS_NAME, OBJ_PATH, IFACE, None)


def call(method, args=None):
    from gi.repository import Gio
    return proxy().call_sync(method, args, Gio.DBusCallFlags.NONE, 1500, None)


def state():
    try:
        res = call("GetState")
        data = json.loads(res.unpack()[0] if isinstance(res.unpack(), tuple) else res.unpack())
        data["daemon"] = True
        return data
    except Exception as e:
        d = dict(FALLBACK)
        d["error"] = f"{type(e).__name__}: {e}".strip()
        return d


def main(argv):
    cmd = argv[1] if len(argv) > 1 else "state"

    if cmd == "state":
        d = state()
        print(json.dumps(d))
        return 0 if d.get("daemon") else 1

    if cmd in ("start", "stop", "toggle"):
        try:
            call({"start": "Start", "stop": "Stop", "toggle": "Toggle"}[cmd])
        except Exception as e:
            print(json.dumps({"ok": False, "error": str(e)}))
            return 1
        print(json.dumps({"ok": True, "state": state()}))
        return 0

    if cmd == "set" and len(argv) >= 4:
        key, raw = argv[2], argv[3]
        if key in ("reverse",):
            value = raw.lower() in ("1", "true", "yes", "on")
            vtype = "b"
        elif key in ("leds", "baud"):
            value = int(raw)
            vtype = "i"
        elif key in ("port", "side", "capture", "drm_device"):
            value = str(raw)
            vtype = "s"
        else:
            value = float(raw)
            vtype = "d"
        try:
            from gi.repository import GLib
            res = call("SetParam", GLib.Variant("(sv)", (key, GLib.Variant(vtype, value))))
            err = res.unpack()[0]
            if err:
                print(json.dumps({"ok": False, "error": err}))
                return 1
        except Exception as e:
            print(json.dumps({"ok": False, "error": str(e)}))
            return 1
        print(json.dumps({"ok": True, "state": state()}))
        return 0

    if cmd == "get" and len(argv) >= 3:
        d = state()
        key = argv[2]
        print(d.get(key, ""))
        return 0 if d.get("daemon") else 1

    print(__doc__)
    return 2


if __name__ == "__main__":
    sys.exit(main(sys.argv))
