use std::path::PathBuf;

use adw::prelude::*;
use adw::{gio, glib};

#[derive(Debug)]
pub struct AppInfo {
    pub app_id: String,
    installed: bool,
    pub name: Option<String>,
    pub description: glib::GString,
}

impl AppInfo {
    pub fn new(app_id: &str) -> Self {
        if let Some(app_info) = gio::DesktopAppInfo::new(&format!("{app_id}.desktop")) {
            Self {
                app_id: app_id.to_string(),
                installed: true,
                name: Some(app_info.name().to_string()),
                description: app_info.description().unwrap_or_else(|| "".into()),
            }
        } else {
            Self::manual(app_id)
        }
    }

    pub fn is_installed(&self) -> bool {
        self.installed
    }

    fn manual(app_id: &str) -> Self {
        let desktop_file = glib::KeyFile::new();

        let result = desktop_file.load_from_dirs(
            format!("{app_id}.desktop"),
            &applications_dirs(),
            glib::KeyFileFlags::NONE,
        );

        let installed = result.is_ok();

        Self {
            app_id: app_id.to_string(),
            installed,
            name: desktop_file
                .locale_string("Desktop Entry", "Name", None)
                .ok()
                .map(|x| x.to_string()),
            description: desktop_file
                .locale_string("Desktop Entry", "Comment", None)
                .unwrap_or_else(|_| "".into()),
        }
    }
}

fn data_dirs() -> Vec<PathBuf> {
    vec![
        // TODO: this should be host data home
        glib::home_dir().join(".local/share/flatpak/exports/share"),
        PathBuf::from("/var/lib/flatpak/exports/share"),
    ]
}

fn applications_dirs() -> Vec<PathBuf> {
    data_dirs()
        .into_iter()
        .map(|x| x.join("applications"))
        .collect()
}
