use crate::app::App;
use ratatui::{
layout::{Alignment, Constraint, Direction, Layout, Rect},
style::{Color, Modifier, Style},
text::{Line, Span},
widgets::{Block, Borders, Clear, Paragraph},
Frame,
};
const COL_SEPARATOR: &str = " │ ";
const COL_SEPARATOR_WIDTH: usize = 5;
const CELL_GUTTER: &str = " ";
const CELL_GUTTER_WIDTH: usize = 2;
pub fn render_help_popup(f: &mut Frame, app: &App) {
let area = f.area();
let max_key_w: usize = app
.shortcut_providers
.iter()
.flat_map(|b| b.entries.iter())
.map(|e| e.key.chars().count())
.max()
.unwrap_or(4);
let max_desc_w: usize = app
.shortcut_providers
.iter()
.flat_map(|b| b.entries.iter())
.map(|e| e.description.chars().count())
.max()
.unwrap_or(10);
let cell_w = max_key_w + CELL_GUTTER_WIDTH + max_desc_w;
let two_col_content_w = (cell_w * 2 + COL_SEPARATOR_WIDTH + 2) as u16;
let desired_w = two_col_content_w + 2; let popup_width = desired_w.min(area.width.saturating_sub(4));
let inner_w = popup_width.saturating_sub(2); let n_cols: usize = if inner_w >= two_col_content_w { 2 } else { 1 };
let total_content_lines: u16 = app
.shortcut_providers
.iter()
.map(|b| {
let rows = (b.entries.len() as u16).div_ceil(n_cols as u16);
1 + 1 + rows + 1 })
.sum::<u16>()
+ 1;
let max_height = (area.height as f32 * 0.90) as u16;
let popup_height = (total_content_lines + 2).min(max_height);
let popup_x = area.x + area.width.saturating_sub(popup_width) / 2;
let popup_y = area.y + area.height.saturating_sub(popup_height) / 2;
let popup_area = Rect::new(popup_x, popup_y, popup_width, popup_height);
f.render_widget(Clear, popup_area);
let outer_block = Block::default()
.borders(Borders::ALL)
.border_style(Style::default().fg(Color::Cyan))
.title(Span::styled(
" ⌨ Keyboard Shortcuts — [any key]: Close ",
Style::default()
.fg(Color::Cyan)
.add_modifier(Modifier::BOLD),
));
f.render_widget(outer_block, popup_area);
let inner = Rect::new(
popup_area.x + 1,
popup_area.y + 1,
popup_area.width.saturating_sub(2),
popup_area.height.saturating_sub(2),
);
let header_w = inner.width as usize;
let mut lines: Vec<Line<'static>> = Vec::new();
for block in &app.shortcut_providers {
let title = block.section.to_uppercase();
lines.push(
Line::from(vec![Span::styled(
format!("{:^width$}", title, width = header_w),
Style::default()
.fg(Color::Black)
.bg(Color::Cyan)
.add_modifier(Modifier::BOLD),
)])
.alignment(Alignment::Left),
);
lines.push(Line::from(Span::raw("")));
for row_entries in block.entries.chunks(n_cols) {
let mut spans: Vec<Span<'static>> = Vec::with_capacity(n_cols * 4);
for (col_idx, entry) in row_entries.iter().enumerate() {
if col_idx > 0 {
spans.push(Span::styled(
COL_SEPARATOR,
Style::default().fg(crate::ui::theme::MUTED_DIM),
));
}
spans.push(Span::styled(
format!("{:>width$}", entry.key, width = max_key_w),
Style::default()
.fg(Color::Yellow)
.add_modifier(Modifier::BOLD),
));
spans.push(Span::raw(CELL_GUTTER));
let desc = if n_cols == 2 && col_idx == 0 {
format!("{:<width$}", entry.description, width = max_desc_w)
} else {
entry.description.to_string()
};
spans.push(Span::styled(desc, Style::default().fg(Color::White)));
}
lines.push(Line::from(spans));
}
lines.push(Line::from(Span::raw("")));
}
let zones = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Min(1), Constraint::Length(1)])
.split(inner);
f.render_widget(Paragraph::new(lines), zones[0]);
f.render_widget(
Paragraph::new(Line::from(vec![Span::styled(
"Press any key to close",
Style::default().fg(crate::ui::theme::MUTED_HINT),
)]))
.alignment(Alignment::Center),
zones[1],
);
}