use crate::graphics::menus::messages::{CONTROLS_TABLE, SNAKE_LOGO};
use crate::graphics::menus::utils_layout::frame_vertically_centered_rect;
use clap::ValueEnum;
use ratatui::style::Stylize;
use ratatui::style::{Color, Modifier, Style};
use ratatui::text::{Line, Span, Text};
use ratatui::widgets::{Block, BorderType, Paragraph};
use ratatui::{DefaultTerminal, Frame};
use std::cmp::PartialEq;
use std::thread::sleep;
use std::time::Duration;
use unicode_segmentation::UnicodeSegmentation;
pub fn display_main_menu(
terminal: &mut DefaultTerminal,
selected_switch_menu_for_display_bracket: &SwitchMenu,
) {
terminal
.draw(|frame| {
let area = frame.area();
big_snake_menu(frame, selected_switch_menu_for_display_bracket);
frame.render_widget(Block::bordered().border_type(BorderType::Double), area);
})
.expect("Unusable terminal render");
sleep(Duration::from_millis(100));
}
fn big_snake_menu(frame: &mut Frame, to_display_switch: &SwitchMenu) {
let mut lines = vec![];
for logo_line in SNAKE_LOGO.lines() {
lines.push(Line::from(logo_line));
}
lines.push(Line::from(get_button_span(to_display_switch)));
for table_line in CONTROLS_TABLE.lines() {
lines.push(Line::from(table_line));
}
lines.push(Line::from("Have a good 🐍 game ! 🎮".green()));
let nb_lines = lines.len();
frame.render_widget(
Paragraph::new(Text::from(lines)).centered(),
frame_vertically_centered_rect(frame.area(), nb_lines),
);
}
pub struct Button {
pub name: &'static str,
pub selected: bool,
}
impl Button {
#[must_use]
pub const fn new(name: &'static str) -> Self {
Self {
name,
selected: false,
}
}
pub fn selected(&mut self, selected: bool) {
self.selected = selected;
}
#[must_use]
pub fn to_spans(&self) -> Vec<Span<'static>> {
if self.selected {
vec![
Span::styled(" [ ", Style::default().fg(Color::Red)).add_modifier(Modifier::BOLD),
Span::raw(self.name),
Span::styled(
" ] ",
Style::default().fg(Color::Red).add_modifier(Modifier::BOLD),
),
]
} else {
let (first, rest) = match self.name.graphemes(true).next() {
Some(grapheme) => {
let rest = &self.name[grapheme.len()..];
(grapheme, rest) }
None => ("", ""), };
vec![
Span::raw("["),
Span::styled(first, Style::default().fg(Color::Yellow)),
Span::raw(format!("{rest}]")),
]
}
}
}
#[derive(PartialEq, ValueEnum, Clone)]
pub enum SwitchMenu {
Highs,
Fruits,
Speed,
Run,
Parameters,
Doc,
Main,
}
const BUTTONS: [(SwitchMenu, Button); 6] = [
(SwitchMenu::Highs, Button::new("Highs💯")),
(SwitchMenu::Fruits, Button::new("Fruit")),
(SwitchMenu::Speed, Button::new("Speed")),
(SwitchMenu::Run, Button::new("Run")),
(SwitchMenu::Parameters, Button::new("Edit⚙️")),
(SwitchMenu::Doc, Button::new("Docℹ️")),
];
fn get_button_span(selected: &SwitchMenu) -> Vec<Span<'static>> {
let mut vec_line_button = vec![Span::raw("↔")];
for (menu, mut button) in BUTTONS {
button.selected(selected == &menu);
vec_line_button.extend(button.to_spans());
}
vec_line_button
}