//! Darstellung des Textbildschirms als Ratatui-Widget.
//!
//! Der Zellenpuffer selbst lebt in `tb_runtime::screen` (Entscheidung
//! 2026-09-03) — hier bleibt nur die Anbindung an das Terminal: die
//! Farbabbildung und das Widget. Da `Widget` und `TextScreen` beide fremd
//! sind, trägt das Widget ein Newtype.

pub use tb_runtime::screen::{Cell, TextScreen, MIN_COLS, MIN_ROWS};

use ratatui::buffer::Buffer;
use ratatui::layout::Rect;
use ratatui::style::{Color, Style};
use ratatui::widgets::Widget;

/// Abbildung der klassischen 16-Farben-Palette auf ANSI-Indexfarben.
/// (Klassisch: 1 = Blau, 4 = Rot — ANSI: 1 = Rot, 4 = Blau usw.)
pub fn basic_color(n: u8) -> Color {
    const MAP: [u8; 16] = [0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15];
    Color::Indexed(MAP[(n & 0x0F) as usize])
}

/// Zeichenbares Gegenstück zu [`TextScreen`].
pub struct ScreenWidget<'a>(pub &'a TextScreen);

/// Clipped viewport; only the terminal owner enforces physical minimum size.
impl Widget for ScreenWidget<'_> {
    fn render(self, area: Rect, buf: &mut Buffer) {
        let cols = self.0.cols().min(area.width as usize);
        let rows = self.0.rows().min(area.height as usize);
        for row in 0..rows {
            for col in 0..cols {
                let c = self.0.cell(row + 1, col + 1);
                if c.fortsetzung {
                    // Die Zelle gehört zum breiten Zeichen davor; das Terminal
                    // belegt sie beim Zeichnen selbst mit.
                    continue;
                }
                if let Some(cell) = buf.cell_mut((area.x + col as u16, area.y + row as u16)) {
                    let mut s = String::new();
                    s.push(c.ch);
                    cell.set_symbol(&s);
                    cell.set_style(Style::default().fg(basic_color(c.fg)).bg(basic_color(c.bg)));
                }
            }
        }
        // Cursor als invertierte Zelle darstellen (Terminal-Cursor wird in
        // der Forms-/Runtime-Schicht später gezielt gesteuert).
        if self.0.cursor_visible && self.0.csrlin() <= rows && self.0.pos() <= cols {
            let (cx, cy) = (
                area.x + (self.0.pos() - 1) as u16,
                area.y + (self.0.csrlin() - 1) as u16,
            );
            if let Some(cell) = buf.cell_mut((cx, cy)) {
                cell.set_style(
                    cell.style()
                        .add_modifier(ratatui::style::Modifier::REVERSED),
                );
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn farbabbildung() {
        assert_eq!(basic_color(1), Color::Indexed(4)); // klassisch Blau
        assert_eq!(basic_color(4), Color::Indexed(1)); // klassisch Rot
        assert_eq!(basic_color(14), Color::Indexed(11)); // Gelb
        assert_eq!(basic_color(15), Color::Indexed(15)); // Weiß
    }
}
