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

import gi

gi.require_version("Gio", "2.0")
from gi.repository import Gio, GLib

DISPLAY_BUS = "org.gnome.Mutter.DisplayConfig"
DISPLAY_PATH = "/org/gnome/Mutter/DisplayConfig"
IDLE_BUS = "org.gnome.Mutter.IdleMonitor"
IDLE_PATH = "/org/gnome/Mutter/IdleMonitor/Core"
POLL_MS = 2000
WAKE_MS = 1500


def name_has_owner(bus, name):
    try:
        res = bus.call_sync(
            "org.freedesktop.DBus",
            "/org/freedesktop/DBus",
            "org.freedesktop.DBus",
            "NameHasOwner",
            GLib.Variant("(s)", (name,)),
            None,
            Gio.DBusCallFlags.NONE,
            2000,
            None,
        )
        return bool(res.unpack()[0])
    except GLib.Error:
        return False


def main():
    if "GNOME" not in os.environ.get("XDG_CURRENT_DESKTOP", ""):
        return 0

    try:
        bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
    except GLib.Error:
        return 0

    if name_has_owner(bus, "org.gnome.Shell.ScreenShield"):
        return 0

    settings = Gio.Settings.new("org.gnome.desktop.session")
    state = {"off": False}

    def set_power(mode):
        bus.call_sync(
            DISPLAY_BUS,
            DISPLAY_PATH,
            "org.freedesktop.DBus.Properties",
            "Set",
            GLib.Variant(
                "(ssv)",
                (DISPLAY_BUS, "PowerSaveMode", GLib.Variant("i", mode)),
            ),
            None,
            Gio.DBusCallFlags.NONE,
            2000,
            None,
        )

    def get_idle_ms():
        res = bus.call_sync(
            IDLE_BUS,
            IDLE_PATH,
            IDLE_BUS,
            "GetIdletime",
            None,
            None,
            Gio.DBusCallFlags.NONE,
            2000,
            None,
        )
        return int(res.unpack()[0])

    def tick():
        try:
            delay = settings.get_uint("idle-delay")
            idle = get_idle_ms()
            if delay > 0 and idle >= delay * 1000 and not state["off"]:
                set_power(3)
                state["off"] = True
            elif state["off"] and idle < WAKE_MS:
                set_power(0)
                state["off"] = False
        except GLib.Error:
            pass
        return True

    GLib.timeout_add(POLL_MS, tick)
    GLib.MainLoop().run()
    return 0


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