1#![allow(clippy::missing_const_for_fn)]
2use std::path::PathBuf;
3
4pub struct ConfigBuilder {
5    diary_path: PathBuf,
6    prefix: String,
7    file_type: String,
8}
9
10impl ConfigBuilder {
11    fn new() -> Self {
12        Self {
13            diary_path: PathBuf::from(""),
14            prefix: "diary".to_owned(),
15            file_type: "md".to_owned(),
16        }
17    }
18
19    #[must_use]
20    pub fn diary_path(mut self, diary_path: PathBuf) -> Self {
21        self.diary_path = diary_path;
22        self
23    }
24    #[must_use]
25    pub fn prefix(mut self, prefix: impl Into<String>) -> Self {
26        self.prefix = prefix.into();
27        self
28    }
29    #[must_use]
30    pub fn file_type(mut self, file_type: impl Into<String>) -> Self {
31        self.file_type = file_type.into();
32        self
33    }
34
35    pub fn build(self) -> Config {
36        let Self {
37            diary_path,
38            prefix,
39            file_type,
40        } = self;
41        Config {
42            diary_path,
43            prefix,
44            file_type,
45        }
46    }
47}
48
49#[derive(Debug, Serialize, Deserialize)]
51pub struct Config {
52    diary_path: PathBuf,
53    prefix: String,
54    file_type: String,
55}
56
57impl Config {
58    pub fn builder() -> ConfigBuilder {
59        ConfigBuilder::new()
60    }
61
62    pub const fn diary_path(&self) -> &PathBuf {
63        &self.diary_path
64    }
65
66    pub const fn prefix(&self) -> &String {
67        &self.prefix
68    }
69
70    pub const fn file_type(&self) -> &String {
71        &self.file_type
72    }
73}
74
75impl Default for Config {
76    fn default() -> Self {
78        ConfigBuilder::new().build()
79    }
80}
81
82#[derive(Default)]
83pub struct ConfigManager {
84    config: Config,
85    location: Option<PathBuf>,
86}
87
88impl ConfigManager {
89    pub const fn location(&self) -> &Option<PathBuf> {
90        &self.location
91    }
92
93    pub const fn config(&self) -> &Config {
94        &self.config
95    }
96
97    pub fn with_location(location: Option<PathBuf>) -> Self {
98        Self {
99            location,
100            ..Default::default()
101        }
102    }
103
104    pub fn read(mut self) -> Result<Self, confy::ConfyError> {
105        let config: Config = match &self.location {
106            Some(l) => confy::load_path(l)?,
107            _ => confy::load("diary", None)?,
108        };
109        self.config = config;
110
111        Ok(self)
112    }
113
114    pub fn write(self) -> Result<(), confy::ConfyError> {
115        match self.location {
116            Some(l) => confy::store_path(l, self.config),
117            _ => confy::store("diary", None, self.config), }
119    }
120
121    #[must_use]
122    pub fn update_config(mut self, config: Config) -> Self {
123        self.config = config;
124        self
125    }
126}
127
128#[cfg(test)]
129mod tests {
130    use std::path::PathBuf;
131
132    use super::{Config, ConfigManager};
133
134    #[test]
135    fn full_config_build() {
136        let cfg = Config::builder()
137            .diary_path(PathBuf::from("/home/"))
138            .prefix("dy")
139            .build();
140
141        assert_eq!(cfg.prefix(), "dy");
142        assert_eq!(cfg.diary_path(), &PathBuf::from("/home/"))
143    }
144
145    #[test]
146    fn config_manager_with_location() {
147        let location = Some(PathBuf::from("/tmp/"));
148
149        let cfg_manager = ConfigManager::with_location(location.clone());
150
151        assert!(cfg_manager.location().clone() == location)
152    }
153}