use egui::{Color32, FontId, Vec2};

use super::Component;
pub use crate::io::display::Display;

impl Component for Display {
    fn title(&self) -> &str {
        "Display"
    }

    fn visible(&mut self) -> &mut bool {
        self.visible()
    }

    fn ui(&mut self, ui: &mut egui::Ui, ctx: &egui::Context) {
        let display_w = self.width();
        let display_h = self.height();
        let data = self.read();

        let font_id = FontId::monospace(12.0);

        let char_width = ui.fonts_mut(|f| f.glyph_width(&font_id, 'W'));
        let line_height = ui.fonts_mut(|f| f.row_height(&font_id));

        #[expect(clippy::cast_precision_loss)]
        let display_size = Vec2::new(
            char_width * display_w as f32,
            line_height * display_h as f32,
        );

        let (rect, _response) = ui.allocate_exact_size(display_size, egui::Sense::all());

        // ui.painter().rect_filled(rect, 0.0, Color32::BLACK);

        // Draw text
        for y in 0..display_h {
            let mut row_text = String::with_capacity(display_w);
            for x in 0..display_w {
                let index = y * display_w + x;
                if index < data.len() {
                    let byte = data[index];
                    let ch = if (32..=126).contains(&byte) {
                        byte as char
                    } else {
                        ' '
                    };
                    row_text.push(ch);
                } else {
                    row_text.push(' ');
                }
            }

            #[expect(clippy::cast_precision_loss)]
            let text_pos = rect.min + Vec2::new(0.0, y as f32 * line_height);

            ui.painter().text(
                text_pos,
                egui::Align2::LEFT_TOP,
                row_text,
                font_id.clone(),
                Color32::WHITE,
            );
        }
    }
}
