1use serde::{Deserialize, Serialize};
6use std::fs;
7use std::path::Path;
8
9#[derive(Debug, Serialize, Deserialize)]
11pub struct CliConfiguration {
12 pub default_format: String,
14
15 pub verbose: bool,
17
18 pub config_file: Option<String>,
20
21 pub color_output: bool,
23
24 pub refresh_interval: u64,
26
27 pub performance: PerformanceConfig,
29
30 pub debug: DebugConfig,
32}
33
34#[derive(Debug, Serialize, Deserialize)]
36pub struct PerformanceConfig {
37 pub realtime_monitoring: bool,
39
40 pub sampling_interval: u64,
42
43 pub history_retention: u64,
45
46 pub threshold_alerts: bool,
48}
49
50#[derive(Debug, Serialize, Deserialize)]
52pub struct DebugConfig {
53 pub detailed_debug: bool,
55
56 pub stack_traces: bool,
58
59 pub memory_profiling: bool,
61
62 pub thread_profiling: bool,
64
65 pub log_level: String,
67}
68
69impl Default for CliConfiguration {
70 fn default() -> Self {
71 Self {
72 default_format: "text".to_string(),
73 verbose: false,
74 config_file: None,
75 color_output: true,
76 refresh_interval: 5,
77 performance: PerformanceConfig::default(),
78 debug: DebugConfig::default(),
79 }
80 }
81}
82
83impl Default for PerformanceConfig {
84 fn default() -> Self {
85 Self {
86 realtime_monitoring: true,
87 sampling_interval: 1000,
88 history_retention: 3600,
89 threshold_alerts: true,
90 }
91 }
92}
93
94impl Default for DebugConfig {
95 fn default() -> Self {
96 Self {
97 detailed_debug: false,
98 stack_traces: false,
99 memory_profiling: false,
100 thread_profiling: false,
101 log_level: "info".to_string(),
102 }
103 }
104}
105
106pub struct ConfigManager {
108 config: CliConfiguration,
109}
110
111impl ConfigManager {
112 pub fn new() -> Self {
114 Self {
115 config: CliConfiguration::default(),
116 }
117 }
118
119 pub fn load_from_file<P: AsRef<Path>>(&mut self, path: P) -> Result<(), Box<dyn std::error::Error>> {
121 let content = fs::read_to_string(path)?;
122 self.config = serde_yaml::from_str(&content)?;
123 Ok(())
124 }
125
126 pub fn save_to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), Box<dyn std::error::Error>> {
128 let content = serde_yaml::to_string(&self.config)?;
129 fs::write(path, content)?;
130 Ok(())
131 }
132
133 pub fn get_config(&self) -> &CliConfiguration {
135 &self.config
136 }
137
138 pub fn update_config(&mut self, new_config: CliConfiguration) {
140 self.config = new_config;
141 }
142
143 pub fn validate(&self) -> Result<(), Vec<String>> {
145 let mut errors = Vec::new();
146
147 if !["text", "json", "yaml"].contains(&self.config.default_format.as_str()) {
149 errors.push("Invalid default format. Must be one of: text, json, yaml".to_string());
150 }
151
152 if self.config.refresh_interval == 0 {
154 errors.push("Refresh interval must be greater than 0".to_string());
155 }
156
157 if self.config.performance.sampling_interval == 0 {
159 errors.push("Performance sampling interval must be greater than 0".to_string());
160 }
161
162 if !["error", "warn", "info", "debug", "trace"].contains(&self.config.debug.log_level.as_str()) {
164 errors.push("Invalid debug log level".to_string());
165 }
166
167 if errors.is_empty() {
168 Ok(())
169 } else {
170 Err(errors)
171 }
172 }
173
174 pub fn generate_template() -> String {
176 let template = CliConfiguration::default();
177 serde_yaml::to_string(&template).unwrap_or_else(|_| "# Error generating template".to_string())
178 }
179}