use common::prelude::Instruction;
use egui::{Context, Ui};

use crate::emulator::{
    system::model::{Command, State},
    ui::interface::Component,
};

pub struct History {
    visible: bool,
}

impl Component for History {
    fn name(&self) -> &'static str {
        "Instruction History"
    }

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

    fn category(&self) -> super::interface::Category {
        super::interface::Category::Control
    }

    fn render(&mut self, state: &mut State, ui: &mut Ui, _ctx: &Context) {
        state.send(Command::HistoryRequest);

        egui::ScrollArea::vertical()
            .id_salt("output_scroll")
            .max_width(400.0)
            .show(ui, |ui| {
                if state.instruction_history.is_empty() {
                    ui.label(
                        egui::RichText::new("No output data")
                            .font(egui::FontId::monospace(12.0))
                            .color(egui::Color32::GRAY),
                    );
                    return;
                }

                egui::Grid::new("output_grid")
                    .spacing([5.0, 2.0]) // Horizontal and vertical spacing
                    .num_columns(4)
                    .striped(false)
                    .show(ui, |ui| {
                        // Process bytes in chunks of 4
                        for (idx, instruction) in
                            state.instruction_history.iter().enumerate()
                        {
                            ui.label(format!("{idx}: "));

                            // Hex column
                            let addr = instruction.0;
                            ui.label(
                                egui::RichText::new(format!("0x{addr:08X}"))
                                    .font(egui::FontId::monospace(12.0))
                                    .color(egui::Color32::from_rgb(255, 200, 200)),
                            );

                            let decoded = Instruction::decode(instruction.1)
                                .unwrap_or(Instruction::Nop);

                            ui.label(
                                egui::RichText::new(decoded.to_string())
                                    .font(egui::FontId::monospace(12.0))
                                    .color(egui::Color32::from_rgb(200, 255, 200)),
                            );

                            ui.end_row();
                        }
                    });
            });
    }
}

impl Default for History {
    fn default() -> Self {
        Self::new()
    }
}

impl History {
    #[must_use]
    pub const fn new() -> Self {
        Self { visible: false }
    }
}
