use std::sync::OnceLock;
use std::time::Duration;
use badterm_core::Terminal;
use badterm_core::sauce;
use badterm_core::screen::{Cell, Color, Look, Screen};
use super::*;
pub const TIME: Duration = Duration::from_secs(2);
pub const COLS: usize = 80;
pub const ROWS: usize = 25;
const LOGO: &[u8] = include_bytes!("../../assets/logo/badterm.ans");
const CORNER_X: usize = 20;
const CORNER_TOP: usize = 14;
const TEXT_X: usize = 1;
fn vga(i: u8) -> Color {
Color::Rgb(Look::standard().rgb(Color::Pc(i)))
}
fn logo() -> &'static [Cell] {
static CELLS: OnceLock<Vec<Cell>> = OnceLock::new();
CELLS.get_or_init(|| {
let (content, _) = sauce::split(LOGO);
let mut term = Terminal::new(COLS, ROWS + 2, 0);
term.screen.ice_colors = true;
term.screen.base_ice = true;
term.feed(content);
(0..ROWS)
.flat_map(|y| term.screen.row(y)[..COLS].to_vec())
.map(|c| {
let (fg, bg, _) = c.resolve(true);
Cell::new(c.ch, Color::Rgb(fg), Color::Rgb(bg))
})
.collect()
})
}
pub fn draw(s: &mut Screen) {
for (i, cell) in logo().iter().enumerate() {
if let Some(c) = s.cell_mut(i % COLS, i / COLS) {
*c = *cell;
}
}
let version = format!("v{}", env!("CARGO_PKG_VERSION"));
let lines = [
(15, "t h e", 7),
(16, "b a d a s s", 15),
(17, "t e r m i n a l", 7),
(19, version.as_str(), 15),
(20, "badterm.com", 11),
(22, "Copyright (C) 2026", 7),
(23, "Bad Cluster", 7),
(24, "GNU GPL v3 or later", 8),
];
for (y, text, fg) in lines {
debug_assert!(y >= CORNER_TOP && TEXT_X + text.chars().count() <= CORNER_X, "{text:?} is outside the corner");
label(s, TEXT_X, y, text, vga(fg), vga(0));
}
}
#[cfg(test)]
mod tests {
use super::*;
fn rows(s: &Screen) -> Vec<String> {
(0..ROWS).map(|y| Screen::row_text(s.row(y))).collect()
}
#[test]
fn logo_and_words() {
let mut s = Screen::new(COLS, ROWS, 0);
draw(&mut s);
let rows = rows(&s);
assert!(rows[19].contains(env!("CARGO_PKG_VERSION")), "{rows:#?}");
assert!(rows[20].contains("badterm.com"), "{rows:#?}");
let inked = rows.iter().filter(|r| r.chars().any(|c| "█▀▄░▒▓".contains(c))).count();
assert!(inked >= 22, "{inked} rows with ink: {rows:#?}");
assert!(logo().iter().any(|c| c.bg == vga(14)), "no yellow backgrounds");
assert!(logo().iter().all(|c| matches!((c.fg, c.bg), (Color::Rgb(_), Color::Rgb(_)))));
}
#[test]
fn corner_is_clear() {
let cells = logo();
for y in CORNER_TOP..ROWS {
for x in 0..CORNER_X {
let c = cells[y * COLS + x];
assert!(c.ch == b' ' && c.bg == vga(0), "the logo has ink at {x},{y}");
}
}
let mut s = Screen::new(COLS, ROWS, 0);
draw(&mut s);
for y in 0..ROWS {
for x in 0..COLS {
let cell = s.row(y)[x];
let ours = y >= CORNER_TOP && x < CORNER_X;
if ours {
continue;
}
assert_eq!(cell, cells[y * COLS + x], "a word spilled out of the corner at {x},{y}");
}
}
}
}