use anyhow::{bail, Result};
use std::collections::HashSet;
use std::process::Command;
use super::profiles::{find_profile, DesktopProfile, PROFILES};
pub struct InstalledStatus {
pub profile: &'static DesktopProfile,
pub installed: bool,
}
fn dpkg_installed() -> HashSet<String> {
let stdout = Command::new("dpkg-query")
.args(["-f", "${Package}\\t${db:Status-Abbrev}\\n", "-W"])
.output()
.map(|o| o.stdout)
.unwrap_or_default();
String::from_utf8_lossy(&stdout)
.lines()
.filter_map(|line| {
let mut parts = line.splitn(2, '\t');
let pkg = parts.next()?.to_string();
let status = parts.next().unwrap_or("").trim();
if status.starts_with("ii") { Some(pkg) } else { None }
})
.collect()
}
pub fn list_desktops() -> Vec<InstalledStatus> {
let installed = dpkg_installed();
PROFILES
.iter()
.map(|p| {
let is_installed = p.packages.iter().any(|pkg| installed.contains(*pkg));
InstalledStatus { profile: p, installed: is_installed }
})
.collect()
}
pub fn install_desktop(name: &str) -> Result<()> {
let profile = find_profile(name)
.ok_or_else(|| anyhow::anyhow!("Unknown desktop environment: {}", name))?;
let mut args = vec!["install", "-y"];
args.extend(profile.packages.iter().copied());
let status = Command::new("apt-get").args(&args).status()?;
if !status.success() {
bail!("Failed to install {}", profile.display_name);
}
Ok(())
}
pub fn remove_desktop(name: &str) -> Result<()> {
let profile = find_profile(name)
.ok_or_else(|| anyhow::anyhow!("Unknown desktop environment: {}", name))?;
let mut args = vec!["remove", "-y"];
args.extend(profile.packages.iter().copied());
let status = Command::new("apt-get").args(&args).status()?;
if !status.success() {
bail!("Failed to remove {}", profile.display_name);
}
Ok(())
}
pub fn switch_desktop(name: &str) -> Result<()> {
install_desktop(name)?;
let profile = find_profile(name).unwrap();
let status = Command::new("dpkg-reconfigure")
.args([profile.display_manager])
.status()?;
if !status.success() {
bail!("Failed to reconfigure display manager to {}", profile.display_manager);
}
println!(
"Display manager switched to {}. Restart display manager to apply.",
profile.display_manager
);
Ok(())
}