use ratatui::prelude::*;
use ratatui::buffer::Buffer;
use crate::app::App;
use super::theme;
const TABLES: &[&str] = &["BLACKJACK", "SLOTS", "ROULETTE", "WAR", "BACCARAT", "V.POKER", "KENO", "SIC BO", "CRAPS"];
const TABLE_ICONS: &[&str] = &["♠ ♥ ♣ ♦", "⟐ ⟐ ⟐", "◎ ◎ ◎", "⚔ ⚔", "9 9 9", "♠ HOLD", "● ● ●", "⚄ ⚄ ⚄", "⚃ ⚁"];
pub fn draw_hub(f: &mut Frame, app: &App, area: Rect) {
let buf = f.buffer_mut();
for y in area.top()..area.bottom() {
for x in area.left()..area.right() {
buf[(x, y)].set_char(' ').set_bg(theme::BG);
}
}
let w = area.width as usize;
let h = area.height as usize;
if h < 10 || w < 40 {
return;
}
let cx = w / 2;
let _vanish_y = 2;
for y in 0..h.min(5) {
let spread = ((5 - y) as f32 / 5.0 * (w as f32 / 2.0 - 4.0)) as usize;
let left = cx.saturating_sub(spread);
let right = (cx + spread).min(w - 1);
let ax = area.left() + left as u16;
let ay = area.top() + y as u16;
if ay < area.bottom() && ax < area.right() {
buf[(ax, ay)].set_char('╲').set_fg(theme::AMBER_DIM);
}
let ax2 = area.left() + right as u16;
if ay < area.bottom() && ax2 < area.right() {
buf[(ax2, ay)].set_char('╱').set_fg(theme::AMBER_DIM);
}
for x in (left + 1)..right {
let ax = area.left() + x as u16;
if ay < area.bottom() && ax < area.right() {
let ch = if y == 0 { '░' } else if y < 2 { '·' } else { ' ' };
let brightness = if y == 0 { theme::DARK_GRAY } else { theme::BG };
buf[(ax, ay)].set_char(ch).set_fg(theme::DARK_GRAY).set_bg(brightness);
}
}
}
let floor_start = h.saturating_sub(h / 3);
for y in floor_start..h {
let depth = y - floor_start;
let spread = ((depth + 3) as f32 / (h as f32 / 3.0) * (w as f32 / 2.0)) as usize;
let left = cx.saturating_sub(spread).max(1);
let right = (cx + spread).min(w - 1);
for x in left..right {
let ax = area.left() + x as u16;
let ay = area.top() + y as u16;
if ay < area.bottom() && ax < area.right() {
let checker = ((x / 3) + (y / 2)) % 2 == 0;
let ch = if checker { '▓' } else { '░' };
let fg = if checker { Color::Rgb(25, 25, 30) } else { Color::Rgb(15, 15, 20) };
buf[(ax, ay)].set_char(ch).set_fg(fg).set_bg(theme::BG);
}
}
}
let sign_text = " ◇ G A M B L E R S D E N ◇ ";
let sign_w = sign_text.len();
let sign_x = (w.saturating_sub(sign_w)) / 2;
let sign_y = 1;
let flicker = (app.frame / 8) % 20 != 0; let sign_color = if flicker { theme::MAGENTA } else { theme::DARK_GRAY };
let border_w = sign_w + 4;
let border_x = sign_x.saturating_sub(2);
let top_border = format!("╔{}╗", "═".repeat(border_w - 2));
let bot_border = format!("╚{}╝", "═".repeat(border_w - 2));
draw_str(buf, area, border_x, sign_y, &top_border, sign_color);
draw_str(buf, area, border_x, sign_y + 1, &format!("║ {} ║", sign_text), sign_color);
draw_str(buf, area, border_x, sign_y + 2, &bot_border, sign_color);
if flicker {
for dx in 0..border_w {
let gx = (border_x + dx) as u16 + area.left();
let gy_top = sign_y as u16 + area.top();
let gy_bot = (sign_y + 2) as u16 + area.top();
if gx < area.right() {
if gy_top > area.top() {
buf[(gx, gy_top - 1)].set_fg(Color::Rgb(60, 0, 50));
}
if gy_bot + 1 < area.bottom() {
buf[(gx, gy_bot + 1)].set_fg(Color::Rgb(60, 0, 50));
}
}
}
}
let table_w = 14;
let table_h = 5;
let gap_x = 2;
let gap_y = 1;
let cols = 3;
let total_grid_w = table_w * cols + gap_x * (cols - 1);
let start_x = (w.saturating_sub(total_grid_w)) / 2;
let start_y = (h / 2).saturating_sub(4);
for (i, &name) in TABLES.iter().enumerate() {
let col = i % cols;
let row = i / cols;
let tx = start_x + col * (table_w + gap_x);
let ty = start_y + row * (table_h + gap_y);
let selected = app.hub_selection == i;
let border_color = if selected { theme::CYAN } else { theme::AMBER_DIM };
let name_color = if selected { theme::WHITE } else { theme::GRAY };
let icon_color = if selected {
match i % 6 {
0 => theme::CYAN,
1 => theme::MAGENTA,
2 => theme::RED,
3 => theme::GREEN,
4 => theme::AMBER,
_ => theme::WHITE,
}
} else {
theme::DARK_GRAY
};
let top = if selected { format!("╔{}╗", "═".repeat(table_w - 2)) } else { format!("┌{}┐", "─".repeat(table_w - 2)) };
let bot = if selected { format!("╚{}╝", "═".repeat(table_w - 2)) } else { format!("└{}┘", "─".repeat(table_w - 2)) };
let sl = if selected { "║" } else { "│" };
let sr = sl;
draw_str(buf, area, tx, ty, &top, border_color);
let icon = TABLE_ICONS[i];
let ipad = (table_w - 2).saturating_sub(icon.chars().count()) / 2;
let icon_line = format!("{}{}{}{}{}", sl, " ".repeat(ipad), icon, " ".repeat((table_w - 2).saturating_sub(ipad + icon.chars().count())), sr);
draw_str_two(buf, area, tx, ty + 1, &icon_line, border_color, icon_color, icon);
let npad = (table_w - 2).saturating_sub(name.len()) / 2;
let name_line = format!("{}{}{}{}{}", sl, " ".repeat(npad), name, " ".repeat((table_w - 2).saturating_sub(npad + name.len())), sr);
draw_str_two(buf, area, tx, ty + 2, &name_line, border_color, name_color, name);
let key_label = format!("[{}]", i + 1);
let kpad = (table_w - 2).saturating_sub(key_label.len()) / 2;
let key_line = format!("{}{}{}{}{}", sl, " ".repeat(kpad), key_label, " ".repeat((table_w - 2).saturating_sub(kpad + key_label.len())), sr);
let key_color = if selected { theme::GREEN } else { theme::DARK_GRAY };
draw_str_two(buf, area, tx, ty + 3, &key_line, border_color, key_color, &key_label);
draw_str(buf, area, tx, ty + 4, &bot, border_color);
}
let particles = [
("·", theme::DARK_GRAY),
("∘", Color::Rgb(40, 40, 50)),
("°", Color::Rgb(35, 30, 25)),
];
for i in 0..12 {
let seed = (app.frame as usize).wrapping_add(i * 7919);
let px = (seed * 31 + i * 17) % w;
let py = (seed * 13 + i * 23) % h;
let (ch, color) = particles[i % particles.len()];
let ax = area.left() + px as u16;
let ay = area.top() + py as u16;
if ax < area.right() && ay < area.bottom() {
let cell = &buf[(ax, ay)];
if cell.symbol() == " " || cell.symbol() == "░" || cell.symbol() == "·" {
buf[(ax, ay)].set_char(ch.chars().next().unwrap()).set_fg(color);
}
}
}
let stats_x = 3;
let stats_y = h.saturating_sub(8);
draw_str(buf, area, stats_x, stats_y, "┌─────────────────────┐", theme::DARK_GRAY);
draw_str(buf, area, stats_x, stats_y + 1, "│ LIFETIME STATS │", theme::GRAY);
draw_str(buf, area, stats_x, stats_y + 2, "├─────────────────────┤", theme::DARK_GRAY);
let games = format!("│ Games: {:>10} │", app.save.games_played);
draw_str(buf, area, stats_x, stats_y + 3, &games, theme::GRAY);
let earned = format!("│ Won: {:>10} │", app.save.total_earned);
draw_str(buf, area, stats_x, stats_y + 4, &earned, theme::GREEN_DIM);
let lost = format!("│ Lost: {:>10} │", app.save.total_lost);
draw_str(buf, area, stats_x, stats_y + 5, &lost, theme::RED_DIM);
let resets = format!("│ Resets:{:>10} │", app.save.resets);
draw_str(buf, area, stats_x, stats_y + 6, &resets, theme::AMBER_DIM);
draw_str(buf, area, stats_x, stats_y + 7, "└─────────────────────┘", theme::DARK_GRAY);
let info_y = h.saturating_sub(2);
let info = "← → SELECT TABLE · ENTER TO SIT · Q QUIT";
let info_x = (w.saturating_sub(info.len())) / 2;
draw_str(buf, area, info_x, info_y, info, theme::GRAY);
}
fn draw_str(buf: &mut Buffer, area: Rect, x: usize, y: usize, s: &str, fg: Color) {
let mut cx = area.left() + x as u16;
let cy = area.top() + y as u16;
if cy >= area.bottom() { return; }
for ch in s.chars() {
if cx >= area.right() { break; }
buf[(cx, cy)].set_char(ch).set_fg(fg);
cx += 1;
}
}
fn draw_str_two(buf: &mut Buffer, area: Rect, x: usize, y: usize, s: &str, border_fg: Color, content_fg: Color, content: &str) {
let mut cx = area.left() + x as u16;
let cy = area.top() + y as u16;
if cy >= area.bottom() { return; }
let content_start = s.find(content).unwrap_or(s.len());
let content_end = content_start + content.len();
for (i, ch) in s.chars().enumerate() {
if cx >= area.right() { break; }
let fg = if i >= content_start && i < content_end { content_fg } else { border_fg };
buf[(cx, cy)].set_char(ch).set_fg(fg);
cx += 1;
}
}