use std::f32;
use std::any::Any;
use egui::{Ui, WidgetText};
use egui_tiles::TileId;
use common::prelude::Register;
use emulator_core::EmulatorHandle;
use crate::ui::Action;
use crate::ui::panels::TilePane;

pub struct Registers {
    state: EmulatorHandle,
}



impl Registers {
    fn section(
        &mut self,
        ui: &mut Ui,
        registers: Vec<(Register, u32)>,
        col_pairs: usize,
        name: &str,
    ) {
        ui.collapsing(name, |ui| {
            egui::Grid::new(name)
                .num_columns(col_pairs * 2)
                .spacing([40.0, 4.0])
                .striped(true)
                .show(ui, |ui| {
                    // only show header if there are multiple rows
                    if registers.len() > col_pairs {
                        for _ in 0..col_pairs {
                            ui.label("Register");
                            ui.label("Value");
                        }
                        ui.end_row();
                    }
                    for chunk in registers.chunks(col_pairs) {
                        for (reg, val) in chunk {
                            ui.label(reg.to_string());
                            ui.label(format!("0x{:08X} ({:012})", val, val));
                        }
                        for _ in chunk.len()..col_pairs {
                            ui.label("");
                            ui.label("");
                        }
                        ui.end_row();
                    }
                });
        });
    }
}

impl Registers {
    pub fn new(state: EmulatorHandle) -> Self {
        Self {
            state,
        }
    }
}

impl TilePane for Registers {
    fn title(&self) -> WidgetText {
        "Registers".into()
    }
    fn ui(&mut self, ui: &mut Ui, _tile_id: TileId) -> Option<Action> {

        ui.set_min_width(200.0);

        let available = ui.available_width();
        let col_pairs = match available {
            0.0..350.0 => 1,
            350.0..600.0 => 2,
            600.0..900.0 => 3,
            f32::MIN..0.0 => unreachable!(),
            _ => 4,
        };

        ui.vertical(|ui| {
            // ── General Purpose ──────────────────────────────────────
            let gp_registers: Vec<(Register, u32)> = (0..=15u8)
                .map(|i| (Register::from_u8(i).unwrap(), self.state.registers()[i as usize]))
                .collect();
            self.section(
                ui,
                gp_registers,
                col_pairs,
                "General Purpose Registers",
            );
            ui.separator();

            // ── Stack ─────────────────────────────────────────────────
            let stack_registers = vec![
                (Register::Spr, self.state.get_register(Register::Spr)),
                (Register::Bpr, self.state.get_register(Register::Bpr)),
            ];
            self.section(ui, stack_registers, col_pairs, "Stack Registers");
            ui.separator();

            // ── Special Purpose ───────────────────────────────────────
            let special_registers = vec![
                (Register::Acc, self.state.get_register(Register::Acc)),
                (Register::Ret, self.state.get_register(Register::Ret)),
                (Register::Idr, self.state.get_register(Register::Idr)),
                (Register::Mmr, self.state.get_register(Register::Mmr)),
            ];
            self.section(
                ui,
                special_registers,
                col_pairs,
                "Special Purpose Registers",
            );
            ui.separator();

            // ── System ────────────────────────────────────────────────
            let system_registers = vec![
                (Register::Pcx, self.state.get_register(Register::Pcx)),
                (Register::Sts, self.state.get_register(Register::Sts)),
                (Register::Cir, self.state.get_register(Register::Cir)),
            ];
            self.section(ui, system_registers, col_pairs, "System Registers");
        });
        None
    }

    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
}
