Skip to main content

gromnie_cli/wizards/
launch.rs

1use ratatui::Frame;
2use std::error::Error;
3
4use gromnie_client::config::GromnieConfig;
5
6use crate::app::App;
7use crate::draw::Draw;
8
9#[derive(Debug, Clone, PartialEq)]
10pub enum WizardStage {
11    Welcome,
12    SelectingServer,
13    SelectingAccount,
14    Confirming,
15    Complete,
16}
17
18#[derive(Clone)]
19pub struct LaunchWizard {
20    #[allow(dead_code)]
21    pub config: GromnieConfig,
22    pub stage: WizardStage,
23    pub selected_server_idx: usize,
24    pub selected_account_idx: usize,
25    pub server_list: Vec<(String, gromnie_client::config::ServerConfig)>,
26    pub account_list: Vec<(String, gromnie_client::config::AccountConfig)>,
27}
28
29impl LaunchWizard {
30    pub fn new(config: GromnieConfig) -> Self {
31        // Guard: require at least one server and one account
32        assert!(
33            !config.servers.is_empty(),
34            "Config must have at least one server configured"
35        );
36        assert!(
37            !config.accounts.is_empty(),
38            "Config must have at least one account configured"
39        );
40
41        let server_list: Vec<_> = config
42            .servers
43            .iter()
44            .map(|(k, v)| (k.clone(), v.clone()))
45            .collect();
46        let account_list: Vec<_> = config
47            .accounts
48            .iter()
49            .map(|(k, v)| (k.clone(), v.clone()))
50            .collect();
51
52        Self {
53            config,
54            stage: WizardStage::Welcome,
55            selected_server_idx: 0,
56            selected_account_idx: 0,
57            server_list,
58            account_list,
59        }
60    }
61
62    pub fn get_selected_server(&self) -> &gromnie_client::config::ServerConfig {
63        &self.server_list[self.selected_server_idx].1
64    }
65
66    pub fn get_selected_account(&self) -> &gromnie_client::config::AccountConfig {
67        &self.account_list[self.selected_account_idx].1
68    }
69}
70
71impl Draw for LaunchWizard {
72    fn draw(self, _app: &mut App, frame: &mut Frame) -> Result<(), Box<dyn Error>> {
73        use ratatui::style::{Color, Style};
74        use ratatui::text::{Line, Span, Text};
75        use ratatui::widgets::Paragraph;
76
77        let mut lines = Vec::new();
78
79        // Always show welcome and config path
80        lines.push(Line::from("Welcome to Gromnie!"));
81        lines.push(Line::from(Span::styled(
82            format!("Config: {}", GromnieConfig::config_path().display()),
83            Style::default().fg(Color::DarkGray),
84        )));
85        lines.push(Line::from(""));
86
87        // Show server selection based on stage
88        match self.stage {
89            WizardStage::Welcome => {
90                // Just show welcome message
91            }
92            WizardStage::SelectingServer => {
93                lines.push(Line::from("? Pick a server"));
94                for (idx, (_name, server)) in self.server_list.iter().enumerate() {
95                    let marker = if idx == self.selected_server_idx {
96                        "●"
97                    } else {
98                        "○"
99                    };
100                    lines.push(Line::from(format!("  {} {}", marker, server)));
101                }
102            }
103            WizardStage::SelectingAccount | WizardStage::Confirming | WizardStage::Complete => {
104                // Show completed server selection
105                lines.push(Line::from("* Pick a server"));
106                let selected_server = &self.server_list[self.selected_server_idx].1;
107                lines.push(Line::from(format!("  {}", selected_server)));
108                lines.push(Line::from(""));
109
110                if self.stage == WizardStage::SelectingAccount {
111                    lines.push(Line::from("? Pick an account"));
112                    for (idx, (_name, account)) in self.account_list.iter().enumerate() {
113                        let marker = if idx == self.selected_account_idx {
114                            "●"
115                        } else {
116                            "○"
117                        };
118                        lines.push(Line::from(format!("  {} {}", marker, account)));
119                    }
120                } else {
121                    // Show completed account selection
122                    lines.push(Line::from("* Pick an account"));
123                    let selected_account = &self.account_list[self.selected_account_idx].1;
124                    lines.push(Line::from(format!("  {}", selected_account)));
125                    lines.push(Line::from(""));
126
127                    if self.stage == WizardStage::Confirming {
128                        lines.push(Line::from("? Ready to log in? <enter>"));
129                    }
130                }
131            }
132        }
133
134        let text = Text::from(lines);
135        let paragraph = Paragraph::new(text);
136        frame.render_widget(paragraph, frame.area());
137
138        Ok(())
139    }
140}