//! Based on https://github.com/pop-os/distinst/blob/d34fd000aabbdae37fc122f6224470e69b817f36/crates/hardware/src/switchable_graphics.rs
//! TODO: Switch to zbus and system76-power-zbus crates when dbus is dropped as a dependency

use dbus::blocking::Connection;
use std::{fs, io, time::Duration};

const POWER: &str = "/etc/modprobe.d/system76-power.conf";
const PRIME_DISCRETE: &str = "/etc/prime-discrete";

static MODPROBE_HYBRID: &[u8] = br#"# Automatically generated by distinst
options nvidia NVreg_DynamicPowerManagement=0x02
blacklist i2c_nvidia_gpu
alias i2c_nvidia_gpu off
"#;

static MODPROBE_INTEGRATED: &[u8] = br#"# Automatically generated by distinst
blacklist i2c_nvidia_gpu
blacklist nouveau
blacklist nvidia
blacklist nvidia-drm
blacklist nvidia-modeset
alias i2c_nvidia_gpu off
alias nouveau off
alias nvidia off
alias nvidia-drm off
alias nvidia-modeset off
"#;

/// Configure graphics mode if switchable graphics is supported.
pub fn reset_to_default() -> io::Result<()> {
    if !has_switchable_graphics() {
        return Ok(());
    }

    let _ = fs::create_dir_all("/etc/modprobe.d/");

    match default_graphics().as_str() {
        "integrated" => {
            info!("disabling external NVIDIA graphics by default");
            fs::write(POWER, MODPROBE_INTEGRATED)?;

            info!("configuring gpu-manager for integrated graphics mode");
            fs::write(PRIME_DISCRETE, "off")?;
        }
        "hybrid" => {
            info!("settings module options for hybrid graphics mode");
            fs::write(POWER, MODPROBE_HYBRID)?;

            info!("configuring gpu-manager for hybrid graphics mode");
            fs::write(PRIME_DISCRETE, "on-demand")?;
        }
        _ => (),
    }

    Ok(())
}

fn default_graphics() -> String {
    if let Ok(conn) = Connection::new_system() {
        let proxy = conn.with_proxy(
            "com.system76.PowerDaemon",
            "/com/system76/PowerDaemon",
            Duration::from_millis(1000),
        );
        let (gfx,): (String,) = proxy
            .method_call("com.system76.PowerDaemon", "GetDefaultGraphics", ())
            .unwrap_or_else(|_| ("nvidia".to_string(),));

        gfx
    } else {
        "nvidia".to_string()
    }
}

fn has_switchable_graphics() -> bool {
    if let Ok(conn) = Connection::new_system() {
        let proxy = conn.with_proxy(
            "com.system76.PowerDaemon",
            "/com/system76/PowerDaemon",
            Duration::from_millis(1000),
        );
        let (switchable,): (bool,) =
            proxy.method_call("com.system76.PowerDaemon", "GetSwitchable", ()).unwrap_or_default();

        // Limit configuring graphics to System76 models
        switchable && (system_vendor() == "System76")
    } else {
        false
    }
}

fn system_vendor() -> String {
    fs::read_to_string("/sys/class/dmi/id/sys_vendor").unwrap_or_default().trim().into()
}
