#!/usr/bin/env python3

import time
import dbus
import dbus.mainloop.glib
import os
from gi.repository import GLib, Notify
import pystray
from PIL import Image
import threading
import queue
import subprocess

import time

start_time = time.time()

# Código de inicialización
print(f"Tiempo después de la inicialización: {
      time.time() - start_time} segundos")

# Define the paths to the PNG icons
ICON_PATHS = {
    "nvidia": "/home/teraflops/Icons/nvidia.png",
    "integrated": "/home/teraflops/Icons/amd.png",
}

# Global variables
systray_icon = None
update_queue = queue.Queue()

# Function to interpret the numerical status into a clearer message


def interpret_gpu_status(status):
    if status == 0:
        return "nvidia"
    elif status == 1:
        return "integrated"
    else:
        return None  # Ignore "switching mode" and other unknown statuses

# Function to update the systray icon


def update_systray_icon(status_message):
    icon_path = ICON_PATHS.get(status_message)
    if icon_path and os.path.exists(icon_path):
        try:
            image = Image.open(icon_path)
            # Put the update information in the queue
            update_queue.put((image, f"GPU: {status_message.capitalize()}"))
            print(f"Queued systray icon update to {status_message}")
        except Exception as e:
            print(f"Error preparing systray icon update: {e}")
    else:
        print(f"No icon found for status: {status_message}")

# Callback for `NotifyGfxStatus`


def on_notify_gfx_status(status):
    print(f"Callback `on_notify_gfx_status` invoked with status: {status}")
    status_message = interpret_gpu_status(status)

    # If the status is "nvidia" or "integrated", update the systray icon
    if status_message:
        print(f"GPU status changed: {status_message}")
        update_systray_icon(status_message)
    else:
        print("Intermediate status detected, no action taken.")

# Functions to execute bash commands


def set_integrated(icon, item):
    print("Setting GPU mode to Integrated...")
    result = subprocess.run(
        ["/usr/bin/supergfxctl", "-m", "Integrated"],
        capture_output=True,
        text=True
    )
    output = result.stdout.strip()
    error = result.stderr.strip()
    # Crear y mostrar la notificación
    if result.returncode == 0:
        message = output if output else "Modo GPU cambiado a Integrado."
        notification = Notify.Notification.new("Modo GPU Cambiado", message)
    else:
        message = error if error else "Error al cambiar a modo Integrado."
        notification = Notify.Notification.new(
            "Error al Cambiar Modo GPU", message)
    notification.show()
    print(message)


def set_hybrid(icon, item):
    print("Setting GPU mode to Hybrid...")
    result = subprocess.run(
        ["/usr/bin/supergfxctl", "-m", "Hybrid"],
        capture_output=True,
        text=True
    )
    output = result.stdout.strip()
    error = result.stderr.strip()
    # Crear y mostrar la notificación
    if result.returncode == 0:
        message = output if output else "Modo GPU cambiado a Híbrido."
        notification = Notify.Notification.new("Modo GPU Cambiado", message)
    else:
        message = error if error else "Error al cambiar a modo Híbrido."
        notification = Notify.Notification.new(
            "Error al Cambiar Modo GPU", message)
    notification.show()
    print(message)


def set_dedicated(icon, item):
    print("Setting GPU mode to Dedicated...")
    result = subprocess.run(
        ["/usr/bin/supergfxctl", "-m", "AsusMuxDgpu"],
        capture_output=True,
        text=True
    )
    output = result.stdout.strip()
    error = result.stderr.strip()
    # Crear y mostrar la notificación
    if result.returncode == 0:
        message = output if output else "Modo GPU cambiado a Dedicado."
        notification = Notify.Notification.new("Modo GPU Cambiado", message)
    else:
        message = error if error else "Error al cambiar a modo Dedicado."
        notification = Notify.Notification.new(
            "Error al Cambiar Modo GPU", message)
    notification.show()
    print(message)

# Initialize the D-Bus loop and signal handlers


def init_dbus_loop():
    # Initialize the D-Bus main loop
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    # Connect to the system bus and get the object
    bus = dbus.SystemBus()
    proxy = bus.get_object("org.supergfxctl.Daemon", "/org/supergfxctl/Gfx")

    # Subscribe to the `NotifyGfxStatus` signal
    bus.add_signal_receiver(
        on_notify_gfx_status,
        dbus_interface="org.supergfxctl.Daemon",
        signal_name="NotifyGfxStatus",
    )

    print("Monitoring GPU signals...")

    # Start the main loop
    loop = GLib.MainLoop()
    loop.run()

# Function to create the systray icon


def create_systray_icon():
    global systray_icon
    # Use a default icon initially
    default_status = "integrated"
    default_icon_path = ICON_PATHS.get(default_status)
    if default_icon_path and os.path.exists(default_icon_path):
        image = Image.open(default_icon_path)
    else:
        # Create a blank icon if default not found
        image = Image.new("RGB", (64, 64), color=(255, 0, 0))

    # Define the menu
    menu = pystray.Menu(
        pystray.MenuItem("Integrated", set_integrated),
        pystray.MenuItem("Hybrid", set_hybrid),
        pystray.MenuItem("Dedicated", set_dedicated),
        pystray.MenuItem("Salir", lambda icon, item: icon.stop())
    )

    systray_icon = pystray.Icon(
        "gpu_status",
        icon=image,
        title=f"GPU: {default_status.capitalize()}",
        menu=menu
    )

    # Function to check the queue and update the icon
    def check_queue():
        try:
            while True:
                new_image, new_title = update_queue.get_nowait()
                systray_icon.icon = new_image
                systray_icon.title = new_title
                systray_icon.visible = True
                print(f"Systray icon updated to {new_title}")
        except queue.Empty:
            pass
        # Schedule the next check
        threading.Timer(1, check_queue).start()

    # Start checking the queue
    check_queue()

    # Start the systray icon
    systray_icon.run()


def main():
    # Inicializar Notify
    Notify.init("GPU Mode Switcher")

    # Start the D-Bus loop in a separate thread
    dbus_thread = threading.Thread(target=init_dbus_loop)
    dbus_thread.daemon = True
    dbus_thread.start()

    # Start the systray icon in the main thread
    create_systray_icon()


if __name__ == "__main__":
    main()
