use crossterm::event::{Event, KeyCode, KeyEvent};
use ratatui::style::{Color, Style};
use std::time::{Duration, Instant};
use rand::Rng;
pub struct MenuItem {
pub label: String,
pub action: MenuAction,
pub highlighted: bool,
pub glitch_intensity: f32,
last_glitch: Instant,
}
impl MenuItem {
pub fn new(label: &str, action: MenuAction) -> Self {
Self {
label: label.to_string(),
action,
highlighted: false,
glitch_intensity: 0.0,
last_glitch: Instant::now(),
}
}
pub fn update(&mut self) {
if self.last_glitch.elapsed() > Duration::from_millis(500) {
let mut rng = rand::thread_rng();
if rng.gen::<f32>() < self.glitch_intensity {
self.last_glitch = Instant::now();
}
}
}
pub fn select(&mut self) {
self.highlighted = true;
self.glitch_intensity = 0.1; }
pub fn deselect(&mut self) {
self.highlighted = false;
self.glitch_intensity = 0.0;
}
pub fn get_style(&self) -> Style {
if self.highlighted {
Style::default().fg(Color::Red)
} else {
Style::default().fg(Color::White)
}
}
}
#[derive(Clone)]
pub enum MenuAction {
StartGame,
ShowRules,
ShowAbout,
Quit,
}
pub struct MainMenu {
pub items: Vec<MenuItem>,
pub selected: usize,
pub last_update: Instant,
}
impl MainMenu {
pub fn new() -> Self {
let mut menu = Self {
items: vec![
MenuItem::new("PLAY", MenuAction::StartGame),
MenuItem::new("RULES", MenuAction::ShowRules),
MenuItem::new("ABOUT", MenuAction::ShowAbout),
MenuItem::new("QUIT", MenuAction::Quit),
],
selected: 0,
last_update: Instant::now(),
};
menu.items[0].select();
menu
}
pub fn update(&mut self) {
for item in &mut self.items {
item.update();
}
}
pub fn handle_input(&mut self, event: Event) -> Option<MenuAction> {
match event {
Event::Key(KeyEvent { code, .. }) => match code {
KeyCode::Up => self.select_prev(),
KeyCode::Down => self.select_next(),
KeyCode::Enter => return Some(self.items[self.selected].action.clone()),
_ => {}
},
_ => {}
}
None
}
fn select_next(&mut self) {
self.items[self.selected].deselect();
self.selected = (self.selected + 1) % self.items.len();
self.items[self.selected].select();
}
fn select_prev(&mut self) {
self.items[self.selected].deselect();
self.selected = if self.selected == 0 {
self.items.len() - 1
} else {
self.selected - 1
};
self.items[self.selected].select();
}
}