1use crate::ui::StatusReporter;
2use data_gov_catalog::Configuration as CatalogConfiguration;
3use std::fmt;
4use std::path::PathBuf;
5use std::sync::Arc;
6
7#[derive(Debug, Clone, PartialEq)]
9pub enum OperatingMode {
10 Interactive,
12 CommandLine,
14}
15
16#[derive(Clone)]
18pub struct DataGovConfig {
19 pub catalog_config: Arc<CatalogConfiguration>,
21 pub mode: OperatingMode,
23 pub base_download_dir: PathBuf,
25 pub user_agent: String,
27 pub max_concurrent_downloads: usize,
29 pub download_timeout_secs: u64,
31 pub status_reporter: Option<Arc<dyn StatusReporter + Send + Sync>>,
33}
34
35impl fmt::Debug for DataGovConfig {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 f.debug_struct("DataGovConfig")
38 .field("catalog_config", &self.catalog_config)
39 .field("mode", &self.mode)
40 .field("base_download_dir", &self.base_download_dir)
41 .field("user_agent", &self.user_agent)
42 .field("max_concurrent_downloads", &self.max_concurrent_downloads)
43 .field("download_timeout_secs", &self.download_timeout_secs)
44 .field(
45 "status_reporter",
46 &self
47 .status_reporter
48 .as_ref()
49 .map(|_| "Some(StatusReporter)"),
50 )
51 .finish()
52 }
53}
54
55impl Default for DataGovConfig {
56 fn default() -> Self {
57 Self {
58 catalog_config: Arc::new(CatalogConfiguration::default()),
59 mode: OperatingMode::Interactive,
60 base_download_dir: Self::get_default_download_dir(),
61 user_agent: concat!("data-gov-rs/", env!("CARGO_PKG_VERSION")).to_string(),
62 max_concurrent_downloads: 3,
63 download_timeout_secs: 300,
64 status_reporter: None,
65 }
66 }
67}
68
69impl DataGovConfig {
70 fn get_default_download_dir() -> PathBuf {
72 if let Some(download_dir) = dirs::download_dir() {
73 download_dir
74 } else {
75 let home = dirs::home_dir().unwrap_or_else(|| PathBuf::from("."));
76 home.join("Downloads")
77 }
78 }
79
80 pub fn new() -> Self {
82 Self::default()
83 }
84
85 pub fn with_download_dir<P: Into<PathBuf>>(mut self, dir: P) -> Self {
87 self.base_download_dir = dir.into();
88 self
89 }
90
91 pub fn with_mode(mut self, mode: OperatingMode) -> Self {
93 self.mode = mode;
94 self
95 }
96
97 pub fn get_base_download_dir(&self) -> PathBuf {
99 match self.mode {
100 OperatingMode::Interactive => self.base_download_dir.clone(),
101 OperatingMode::CommandLine => {
102 std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."))
103 }
104 }
105 }
106
107 pub fn get_dataset_download_dir(&self, dataset_name: &str) -> PathBuf {
109 self.get_base_download_dir().join(dataset_name)
110 }
111
112 pub fn with_base_url<S: Into<String>>(mut self, base_url: S) -> Self {
114 let mut catalog_config = (*self.catalog_config).clone();
115 catalog_config.base_path = base_url.into();
116 self.catalog_config = Arc::new(catalog_config);
117 self
118 }
119
120 pub fn with_user_agent<S: Into<String>>(mut self, user_agent: S) -> Self {
122 self.user_agent = user_agent.into();
123 let mut catalog_config = (*self.catalog_config).clone();
124 catalog_config.user_agent = Some(self.user_agent.clone());
125 self.catalog_config = Arc::new(catalog_config);
126 self
127 }
128
129 pub fn with_max_concurrent_downloads(mut self, max: usize) -> Self {
131 self.max_concurrent_downloads = max.max(1);
132 self
133 }
134
135 pub fn with_download_timeout(mut self, timeout_secs: u64) -> Self {
137 self.download_timeout_secs = timeout_secs;
138 self
139 }
140
141 pub fn with_status_reporter<R>(mut self, reporter: Arc<R>) -> Self
143 where
144 R: StatusReporter + Send + Sync + 'static,
145 {
146 self.status_reporter = Some(reporter);
147 self
148 }
149
150 pub fn without_status_reporter(mut self) -> Self {
152 self.status_reporter = None;
153 self
154 }
155
156 pub fn status_reporter(&self) -> Option<&Arc<dyn StatusReporter + Send + Sync>> {
158 self.status_reporter.as_ref()
159 }
160}