use anyhow::Result;
use serde::Deserialize;
use serde_json::from_slice;
use std::{fmt::Display, fs::read, path::PathBuf};
use typed_builder::TypedBuilder;
use versions::Versioning;
use crate::Internal;
#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct IPathObject {
pub id: isize,
pub priority: isize,
#[builder(setter(into))]
pub value: String,
pub enabled: bool,
#[serde(rename = "isWritable")]
#[builder(default, setter(strip_option))]
pub writable: Option<bool>,
}
#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct RepoPath {
#[builder(setter(into))]
pub value: String,
pub enabled: bool,
pub priority: isize,
pub id: isize,
}
#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
#[builder(field_defaults(setter(into)))]
pub struct Rectangle {
pub x: isize,
pub y: isize,
pub width: isize,
pub height: isize,
}
#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ProxySettingTypes {
None,
Env,
Manual,
}
#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
pub enum InstallationPreference {
RepoOrder,
LegacyStyle,
NewStyle,
}
#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
#[builder(field_defaults(default, setter(strip_option)))]
pub struct Settings {
#[builder(setter(into))]
pub archives: Option<Vec<RepoPath>>,
#[serde(rename = "cacheTimeout")]
pub cache_timeout: Option<isize>,
#[serde(rename = "installPath")]
pub install_path: Option<IPathObject>,
#[serde(rename = "readOnlyInstallationPaths")]
#[builder(setter(into))]
pub read_only_installation_paths: Option<Vec<IPathObject>>,
#[serde(rename = "cfgVersion")]
pub cfg_version: Option<isize>,
#[serde(rename = "guiBounds")]
pub gui_bounds: Option<Rectangle>,
#[serde(rename = "guiMaximized")]
pub gui_maximized: Option<bool>,
#[serde(rename = "powershellPath")]
pub powershell_path: Option<PathBuf>,
#[serde(rename = "tempDirectory")]
pub temp_directory: Option<PathBuf>,
#[serde(rename = "multiUser")]
pub multi_user: Option<bool>,
#[serde(rename = "projectsDefault")]
#[builder(setter(into))]
pub projects_default: Option<String>,
#[serde(rename = "enableRemoteManifests")]
pub enable_remote_manifests: Option<bool>,
#[serde(rename = "manifestRepos")]
#[builder(setter(into))]
pub manifest_repos: Option<Vec<IPathObject>>,
#[serde(rename = "projects")]
#[builder(setter(into))]
pub projects: Option<Vec<IPathObject>>,
#[serde(rename = "manifests")]
#[builder(setter(into))]
pub manifests: Option<Vec<IPathObject>>,
#[serde(rename = "keyStore")]
#[builder(setter(into))]
pub key_store: Option<Vec<IPathObject>>,
#[serde(rename = "ignoreLegacyPlatformRepoDeprecation")]
pub ignore_legacy_platform_repo_deprecation: Option<bool>,
#[serde(rename = "proxySettingsToUse")]
pub proxy_settings_to_use: Option<ProxySettingTypes>,
#[serde(rename = "httpsProxy")]
#[builder(setter(into))]
pub https_proxy: Option<String>,
#[serde(rename = "httpProxy")]
#[builder(setter(into))]
pub http_proxy: Option<String>,
#[serde(rename = "noProxy")]
#[builder(setter(into))]
pub no_proxy: Option<String>,
#[serde(rename = "AuthenticationConfig")]
#[builder(setter(into))]
pub authentication_config: Option<String>,
#[serde(rename = "logfile")]
#[builder(setter(into))]
pub logfile: Option<String>,
#[serde(rename = "preferPackageType")]
pub prefer_package_type: Option<InstallationPreference>,
}
impl Settings {
pub fn get() -> Result<Self> {
Ok(from_slice(&read(Internal::cfg_file_path()?)?)?)
}
}
#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct InstalledPackage {
#[serde(rename = "pkgNumber")]
pub package_number: isize,
pub version: String,
#[builder(setter(into))]
pub name: String,
#[builder(default, setter(into))]
pub paths: Vec<PathBuf>,
}
impl InstalledPackage {
pub fn version(&self) -> Versioning {
Versioning::new(&self.version).expect("Failed to parse installed package version")
}
}
#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct AvailablePackage {
#[serde(rename = "pkgNumber")]
pub package_number: isize,
pub version: String,
#[builder(setter(into))]
pub name: String,
pub installed: bool,
}
impl AvailablePackage {
pub fn version(&self) -> Versioning {
Versioning::new(&self.version).expect("Failed to parse available package version")
}
}
#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
#[builder(field_defaults(default, setter(strip_option, into)))]
pub struct Packages {
#[serde(rename = "installedPackages")]
pub installed_packages: Option<Vec<InstalledPackage>>,
#[serde(rename = "availablePackages")]
pub available_packages: Option<Vec<AvailablePackage>>,
}
impl Packages {
pub fn sort(&mut self) {
if let Some(installed_packages) = self.installed_packages.as_mut() {
installed_packages.sort_by_key(|b| std::cmp::Reverse(b.version()))
}
}
}
#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
pub struct ProjectPackage {
#[serde(rename = "pkgNumber")]
pub package_number: isize,
#[builder(setter(into))]
pub version: String,
}
impl Display for ProjectPackage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}-{}", self.package_number, self.version)
}
}
impl ProjectPackage {
pub fn version(&self) -> Versioning {
Versioning::new(&self.version).expect("Failed to parse project package version")
}
}
#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct Project {
#[builder(setter(into))]
pub name: String,
#[builder(setter(into))]
pub description: String,
pub path: PathBuf,
#[builder(default, setter(into))]
pub packages: Vec<ProjectPackage>,
}
#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
#[builder(field_defaults(default, setter(into)))]
pub struct Projects {
pub projects: Vec<Project>,
}
#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct Platform {
#[builder(setter(into))]
pub name: String,
#[builder(setter(into))]
pub group: String,
#[builder(setter(into))]
pub path: String,
pub remote: bool,
}
#[derive(TypedBuilder, Deserialize, Clone, Debug, PartialEq, Eq)]
#[builder(field_defaults(default, setter(into)))]
pub struct Platforms {
pub platforms: Vec<Platform>,
}