speedtest-tui 0.1.1

A terminal-based network speed test tool with real-time gauges and graphs
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Config {
    #[serde(default)]
    pub general: GeneralConfig,
    #[serde(default)]
    pub theme: ThemeConfig,
    #[serde(default)]
    pub providers: ProvidersConfig,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GeneralConfig {
    #[serde(default = "default_provider")]
    pub default_provider: String,
    #[serde(default = "default_true")]
    pub auto_save_results: bool,
    #[serde(default = "default_duration")]
    pub test_duration_seconds: u64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThemeConfig {
    #[serde(default = "default_theme")]
    pub name: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ProvidersConfig {
    #[serde(default)]
    pub custom: CustomProviderConfig,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CustomProviderConfig {
    #[serde(default)]
    pub enabled: bool,
    #[serde(default = "default_download_url")]
    pub download_url: String,
    #[serde(default = "default_upload_url")]
    pub upload_url: String,
}

fn default_provider() -> String {
    "cloudflare".to_string()
}

fn default_true() -> bool {
    true
}

fn default_duration() -> u64 {
    15
}

fn default_theme() -> String {
    "dark".to_string()
}

fn default_download_url() -> String {
    "http://localhost:8080/download".to_string()
}

fn default_upload_url() -> String {
    "http://localhost:8080/upload".to_string()
}

impl Default for GeneralConfig {
    fn default() -> Self {
        Self {
            default_provider: default_provider(),
            auto_save_results: default_true(),
            test_duration_seconds: default_duration(),
        }
    }
}

impl Default for ThemeConfig {
    fn default() -> Self {
        Self {
            name: default_theme(),
        }
    }
}

impl Default for CustomProviderConfig {
    fn default() -> Self {
        Self {
            enabled: false,
            download_url: default_download_url(),
            upload_url: default_upload_url(),
        }
    }
}

impl Config {
    pub fn config_dir() -> Result<PathBuf> {
        let dir = dirs::home_dir()
            .ok_or_else(|| anyhow::anyhow!("Could not find home directory"))?
            .join(".speedtest-tui");

        if !dir.exists() {
            std::fs::create_dir_all(&dir)?;
        }

        Ok(dir)
    }

    pub fn config_path() -> Result<PathBuf> {
        Ok(Self::config_dir()?.join("config.toml"))
    }

    pub fn load() -> Result<Self> {
        let path = Self::config_path()?;

        if path.exists() {
            let content = std::fs::read_to_string(&path)?;
            let config: Config = toml::from_str(&content)?;
            Ok(config)
        } else {
            let config = Config::default();
            config.save()?;
            Ok(config)
        }
    }

    pub fn save(&self) -> Result<()> {
        let path = Self::config_path()?;
        let content = toml::to_string_pretty(self)?;
        std::fs::write(path, content)?;
        Ok(())
    }
}