rush_sync_server/commands/
registry.rs

1// =====================================================
2// FILE: commands/registry.rs - KOMPLETT IMPLEMENTIERT
3// =====================================================
4
5use super::command::Command;
6use crate::core::prelude::*;
7use std::collections::HashMap;
8
9/// Zentrale Registry für alle Commands - HOCHPERFORMANT & ROBUST
10pub struct CommandRegistry {
11    commands: Vec<Box<dyn Command>>,
12    name_map: HashMap<String, usize>,
13    initialized: bool,
14}
15
16impl CommandRegistry {
17    /// Neue leere Registry erstellen
18    pub fn new() -> Self {
19        Self {
20            commands: Vec::new(),
21            name_map: HashMap::new(),
22            initialized: false,
23        }
24    }
25
26    /// Command registrieren - CHAIN-ABLE
27    pub fn register<T: Command>(&mut self, command: T) -> &mut Self {
28        let name = command.name().to_lowercase();
29        let index = self.commands.len();
30
31        self.commands.push(Box::new(command));
32        self.name_map.insert(name, index);
33
34        //log::debug!("Command registered: {}", self.commands[index].name());
35        self
36    }
37
38    /// Registriert einen Boxed Command (für Plugins)
39    pub fn register_boxed(&mut self, command: Box<dyn Command>) -> &mut Self {
40        let name = command.name().to_lowercase();
41        let index = self.commands.len();
42
43        self.commands.push(command);
44        self.name_map.insert(name, index);
45
46        log::debug!("Boxed command registered: {}", self.commands[index].name());
47        self
48    }
49
50    /// Registry finalisieren - sortiert nach Priorität
51    pub fn initialize(&mut self) -> &mut Self {
52        if self.initialized {
53            return self;
54        }
55
56        // Einfache Sortierung nach Priorität - die Commands sind bereits in Boxen
57        // Wir sortieren nur die Indizes und bauen name_map neu auf
58        self.name_map.clear();
59        for (new_idx, cmd) in self.commands.iter().enumerate() {
60            self.name_map.insert(cmd.name().to_lowercase(), new_idx);
61        }
62
63        self.initialized = true;
64        // log::debug!(
65        //     "CommandRegistry initialized with {} commands",
66        //     self.commands.len()
67        // );
68        self
69    }
70
71    /// Findet Command basierend auf Input
72    pub fn find_command(&self, input: &str) -> Option<&dyn Command> {
73        let input = input.trim().to_lowercase();
74
75        // Erst exakte Übereinstimmung via name_map
76        if let Some(&index) = self.name_map.get(&input) {
77            return self.commands.get(index).map(|cmd| cmd.as_ref());
78        }
79
80        // Dann pattern matching (nach Priorität sortiert)
81        for cmd in &self.commands {
82            if cmd.is_available() && cmd.matches(&input) {
83                return Some(cmd.as_ref());
84            }
85        }
86
87        None
88    }
89
90    /// Führt Command synchron aus
91    pub fn execute_sync(&self, command: &str, args: &[&str]) -> Option<Result<String>> {
92        self.find_command(command).map(|cmd| cmd.execute_sync(args))
93    }
94
95    /// Führt Command asynchron aus
96    pub async fn execute_async(&self, command: &str, args: &[&str]) -> Option<Result<String>> {
97        if let Some(cmd) = self.find_command(command) {
98            Some(cmd.execute_async(args).await)
99        } else {
100            None
101        }
102    }
103
104    /// Listet alle verfügbaren Commands auf
105    pub fn list_commands(&self) -> Vec<(&str, &str)> {
106        self.commands
107            .iter()
108            .filter(|cmd| cmd.is_available())
109            .map(|cmd| (cmd.name(), cmd.description()))
110            .collect()
111    }
112
113    /// Debug-Informationen
114    pub fn debug_info(&self) -> String {
115        let total = self.commands.len();
116        let available = self
117            .commands
118            .iter()
119            .filter(|cmd| cmd.is_available())
120            .count();
121        let async_support = self
122            .commands
123            .iter()
124            .filter(|cmd| cmd.supports_async())
125            .count();
126
127        format!(
128            "CommandRegistry: {} total, {} available, {} async-capable, initialized: {}",
129            total, available, async_support, self.initialized
130        )
131    }
132
133    /// Anzahl registrierter Commands
134    pub fn len(&self) -> usize {
135        self.commands.len()
136    }
137
138    /// Ist Registry leer?
139    pub fn is_empty(&self) -> bool {
140        self.commands.is_empty()
141    }
142}
143
144impl Default for CommandRegistry {
145    fn default() -> Self {
146        Self::new()
147    }
148}