1use super::{Plugin, PluginContext, PluginError, PluginMetadata};
11use std::collections::HashMap;
12use std::path::Path;
13use std::sync::Arc;
14use tracing::{debug, error, info, warn};
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18pub enum PluginState {
19 Registered,
21 Initialized,
23 Enabled,
25 Disabled,
27 Error,
29}
30
31struct PluginWrapper {
33 plugin: Arc<dyn Plugin>,
34 state: PluginState,
35}
36
37pub struct PluginManager {
69 plugins: HashMap<String, PluginWrapper>,
70 api_version: String,
71}
72
73impl PluginManager {
74 pub fn new() -> Self {
76 Self {
77 plugins: HashMap::new(),
78 api_version: "1.0.0".to_string(),
79 }
80 }
81
82 pub fn with_api_version(api_version: impl Into<String>) -> Self {
84 Self {
85 plugins: HashMap::new(),
86 api_version: api_version.into(),
87 }
88 }
89
90 pub fn register(&mut self, plugin: Arc<dyn Plugin>) -> Result<(), PluginError> {
102 let metadata = plugin.metadata();
103 let name = metadata.name.clone();
104
105 if self.plugins.contains_key(&name) {
107 return Err(PluginError::AlreadyRegistered(name));
108 }
109
110 info!(
111 "Registering plugin: {} v{} by {}",
112 name, metadata.version, metadata.author
113 );
114
115 if !self.is_compatible_version(&metadata.api_version) {
117 return Err(PluginError::VersionMismatch(format!(
118 "Plugin {} requires API version {}, but {} is supported",
119 name, metadata.api_version, self.api_version
120 )));
121 }
122
123 self.plugins.insert(
125 name.clone(),
126 PluginWrapper {
127 plugin,
128 state: PluginState::Registered,
129 },
130 );
131
132 debug!("Plugin {} registered successfully", name);
133 Ok(())
134 }
135
136 pub fn unregister(&mut self, name: &str) -> Result<(), PluginError> {
147 let wrapper = self
148 .plugins
149 .get(name)
150 .ok_or_else(|| PluginError::NotFound(name.to_string()))?;
151
152 if wrapper.state == PluginState::Enabled {
153 return Err(PluginError::General(format!(
154 "Plugin {} must be disabled before unregistering",
155 name
156 )));
157 }
158
159 self.plugins.remove(name);
160 info!("Unregistered plugin: {}", name);
161 Ok(())
162 }
163
164 pub async fn initialize(&mut self, name: &str) -> Result<(), PluginError> {
169 let wrapper = self
170 .plugins
171 .get_mut(name)
172 .ok_or_else(|| PluginError::NotFound(name.to_string()))?;
173
174 if wrapper.state != PluginState::Registered {
175 return Ok(()); }
177
178 info!("Initializing plugin: {}", name);
179
180 match wrapper.plugin.init().await {
182 Ok(()) => {
183 wrapper.state = PluginState::Initialized;
184 info!("Plugin {} initialized successfully", name);
185 Ok(())
186 }
187 Err(e) => {
188 wrapper.state = PluginState::Error;
189 error!("Failed to initialize plugin {}: {}", name, e);
190 Err(e)
191 }
192 }
193 }
194
195 pub fn enable(&mut self, name: &str) -> Result<(), PluginError> {
205 let wrapper = self
206 .plugins
207 .get_mut(name)
208 .ok_or_else(|| PluginError::NotFound(name.to_string()))?;
209
210 match wrapper.state {
211 PluginState::Initialized | PluginState::Disabled => {
212 wrapper.state = PluginState::Enabled;
213 info!("Enabled plugin: {}", name);
214 Ok(())
215 }
216 PluginState::Enabled => {
217 debug!("Plugin {} is already enabled", name);
218 Ok(())
219 }
220 PluginState::Registered => Err(PluginError::General(format!(
221 "Plugin {} must be initialized before enabling",
222 name
223 ))),
224 PluginState::Error => Err(PluginError::General(format!(
225 "Plugin {} is in error state",
226 name
227 ))),
228 }
229 }
230
231 pub fn disable(&mut self, name: &str) -> Result<(), PluginError> {
239 let wrapper = self
240 .plugins
241 .get_mut(name)
242 .ok_or_else(|| PluginError::NotFound(name.to_string()))?;
243
244 if wrapper.state == PluginState::Enabled {
245 wrapper.state = PluginState::Disabled;
246 info!("Disabled plugin: {}", name);
247 } else {
248 debug!("Plugin {} is already disabled", name);
249 }
250
251 Ok(())
252 }
253
254 pub fn active_plugins(&self) -> Vec<Arc<dyn Plugin>> {
258 self.plugins
259 .iter()
260 .filter(|(_, wrapper)| wrapper.state == PluginState::Enabled)
261 .map(|(_, wrapper)| Arc::clone(&wrapper.plugin))
262 .collect()
263 }
264
265 pub fn all_plugins(&self) -> Vec<(PluginMetadata, PluginState)> {
267 self.plugins
268 .values()
269 .map(|wrapper| (wrapper.plugin.metadata().clone(), wrapper.state))
270 .collect()
271 }
272
273 pub fn get_state(&self, name: &str) -> Option<PluginState> {
275 self.plugins.get(name).map(|wrapper| wrapper.state)
276 }
277
278 pub fn is_enabled(&self, name: &str) -> bool {
280 self.plugins
281 .get(name)
282 .map(|wrapper| wrapper.state == PluginState::Enabled)
283 .unwrap_or(false)
284 }
285
286 pub async fn init_all(&mut self) -> Result<(), PluginError> {
296 let plugin_names: Vec<String> = self
297 .plugins
298 .iter()
299 .filter(|(_, wrapper)| wrapper.state == PluginState::Registered)
300 .map(|(name, _)| name.clone())
301 .collect();
302
303 let mut errors = Vec::new();
304
305 for name in plugin_names {
306 if let Err(e) = self.initialize(&name).await {
307 errors.push((name, e));
308 }
309 }
310
311 if !errors.is_empty() {
312 let (name, error) = &errors[0];
313 return Err(PluginError::InitFailed(format!(
314 "Failed to initialize plugin {}: {}",
315 name, error
316 )));
317 }
318
319 info!("All plugins initialized successfully");
320 Ok(())
321 }
322
323 pub fn enable_all(&mut self) -> Result<(), PluginError> {
325 let plugin_names: Vec<String> = self
326 .plugins
327 .iter()
328 .filter(|(_, wrapper)| wrapper.state == PluginState::Initialized)
329 .map(|(name, _)| name.clone())
330 .collect();
331
332 for name in plugin_names {
333 self.enable(&name)?;
334 }
335
336 info!("All plugins enabled");
337 Ok(())
338 }
339
340 pub fn disable_all(&mut self) -> Result<(), PluginError> {
342 let plugin_names: Vec<String> = self.plugins.keys().cloned().collect();
343
344 for name in plugin_names {
345 self.disable(&name)?;
346 }
347
348 info!("All plugins disabled");
349 Ok(())
350 }
351
352 pub async fn shutdown_all(&mut self) -> Result<(), PluginError> {
356 let plugin_names: Vec<String> = self.plugins.keys().cloned().collect();
357
358 for name in plugin_names {
359 info!("Shutting down plugin: {}", name);
360
361 if let Some(wrapper) = self.plugins.get(&name) {
362 if let Err(e) = wrapper.plugin.shutdown().await {
364 error!("Error shutting down plugin {}: {}", name, e);
365 }
366 }
367 }
368
369 self.plugins.clear();
370 info!("All plugins shut down");
371 Ok(())
372 }
373
374 pub async fn execute_before_hooks(
379 &self,
380 hook_name: &str,
381 context: &PluginContext,
382 ) -> Result<(), PluginError> {
383 for plugin in self.active_plugins() {
384 if let Err(e) = plugin.before_hook(hook_name, context).await {
385 error!(
386 "Plugin {} failed on hook {}: {}",
387 plugin.metadata().name,
388 hook_name,
389 e
390 );
391 return Err(e);
392 }
393 }
394 Ok(())
395 }
396
397 pub async fn execute_after_hooks(
402 &self,
403 hook_name: &str,
404 context: &PluginContext,
405 ) -> Result<(), PluginError> {
406 for plugin in self.active_plugins() {
407 if let Err(e) = plugin.after_hook(hook_name, context).await {
408 warn!(
410 "Plugin {} failed on after hook {}: {}",
411 plugin.metadata().name,
412 hook_name,
413 e
414 );
415 }
416 }
417 Ok(())
418 }
419
420 pub fn load_from_directory(&mut self, _path: impl AsRef<Path>) -> Result<(), PluginError> {
425 warn!("Dynamic plugin loading not yet implemented");
427 Ok(())
428 }
429
430 pub fn list_plugins(&self) -> Vec<(PluginMetadata, PluginState)> {
432 self.all_plugins()
433 }
434
435 pub fn count_by_state(&self) -> HashMap<PluginState, usize> {
437 let mut counts = HashMap::new();
438 for wrapper in self.plugins.values() {
439 *counts.entry(wrapper.state).or_insert(0) += 1;
440 }
441 counts
442 }
443
444 fn is_compatible_version(&self, plugin_version: &str) -> bool {
446 plugin_version == self.api_version
449 }
450}
451
452impl Default for PluginManager {
453 fn default() -> Self {
454 Self::new()
455 }
456}
457
458#[cfg(test)]
459mod tests {
460 use super::*;
461 use crate::plugin::{PluginBuilder, PluginMetadata};
462 use async_trait::async_trait;
463
464 struct MockPlugin {
465 metadata: PluginMetadata,
466 }
467
468 impl MockPlugin {
469 fn new(name: &str) -> Self {
470 let metadata = PluginBuilder::new(name, "1.0.0")
471 .author("Test")
472 .description("Test plugin")
473 .build();
474 Self { metadata }
475 }
476 }
477
478 #[async_trait]
479 impl Plugin for MockPlugin {
480 fn metadata(&self) -> &PluginMetadata {
481 &self.metadata
482 }
483 }
484
485 #[tokio::test]
486 async fn test_plugin_registration() {
487 let mut manager = PluginManager::new();
488 let plugin = Arc::new(MockPlugin::new("test_plugin"));
489
490 assert!(manager.register(plugin).is_ok());
491 assert!(manager.plugins.contains_key("test_plugin"));
492 }
493
494 #[tokio::test]
495 async fn test_plugin_lifecycle() {
496 let mut manager = PluginManager::new();
497 let plugin = Arc::new(MockPlugin::new("test_plugin"));
498
499 manager.register(plugin).unwrap();
500 assert_eq!(
501 manager.get_state("test_plugin"),
502 Some(PluginState::Registered)
503 );
504
505 manager.initialize("test_plugin").await.unwrap();
506 assert_eq!(
507 manager.get_state("test_plugin"),
508 Some(PluginState::Initialized)
509 );
510
511 manager.enable("test_plugin").unwrap();
512 assert_eq!(manager.get_state("test_plugin"), Some(PluginState::Enabled));
513 assert!(manager.is_enabled("test_plugin"));
514
515 manager.disable("test_plugin").unwrap();
516 assert_eq!(
517 manager.get_state("test_plugin"),
518 Some(PluginState::Disabled)
519 );
520 assert!(!manager.is_enabled("test_plugin"));
521 }
522
523 #[tokio::test]
524 async fn test_active_plugins() {
525 let mut manager = PluginManager::new();
526 let plugin1 = Arc::new(MockPlugin::new("plugin1"));
527 let plugin2 = Arc::new(MockPlugin::new("plugin2"));
528
529 manager.register(plugin1).unwrap();
530 manager.register(plugin2).unwrap();
531
532 manager.initialize("plugin1").await.unwrap();
533 manager.initialize("plugin2").await.unwrap();
534
535 manager.enable("plugin1").unwrap();
536
537 let active = manager.active_plugins();
538 assert_eq!(active.len(), 1);
539 assert_eq!(active[0].metadata().name, "plugin1");
540 }
541}