use std::{f32, sync::Arc};
use std::any::Any;
use egui::{Ui, WidgetText};
use egui_tiles::TileId;
use common::prelude::Register;
use emulator_core::processor::state::SharedState;
use crate::ui::components::memory::MemoryInspector;
use crate::ui::debugger::Action;
use crate::ui::debugger::panels::TilePane;
use super::Component;

pub struct Registers {
    state: Arc<SharedState>,
    visible: bool,
}

impl TilePane for Registers {
    fn title(&self) -> WidgetText {
        "Registers".into()
    }

    fn ui(&mut self, ui: &mut Ui, _tile_id: TileId) -> Option<Action> {
        Component::ui(self, ui);
        None
    }

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

impl Registers {
    fn section(
        &mut self,
        ui: &mut egui::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} ({})", val, val));
                        }
                        for _ in chunk.len()..col_pairs {
                            ui.label("");
                            ui.label("");
                        }
                        ui.end_row();
                    }
                });
        });
    }
}

impl Registers {
    pub fn new(state: Arc<SharedState>) -> Self {
        Self {
            state,
            visible: false,
        }
    }
}

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

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

    fn ui(&mut self, ui: &mut egui::Ui) {
        ui.set_min_width(200.0);

        let state = self.state.proc.load();
        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(), 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, state.registers[Register::Spr as usize]),
                (Register::Bpr, state.registers[Register::Bpr as usize]),
            ];
            self.section(ui, stack_registers, col_pairs, "Stack Registers");
            ui.separator();

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

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