use eframe::egui;
use core::computers::rom_only::RomOnlyComputer;
use core::periph::at28c256::At28C256;

struct RomGui {
    computer: RomOnlyComputer,
    address_input: String,
    data_input: String,
    last_result: Option<u8>,
}

impl Default for RomGui {
    fn default() -> Self {
        Self {
            computer: RomOnlyComputer {
                rom: At28C256::new(0x0000, 0x3fff, [0xff; 0x4000].to_vec()),
                data_bus: 0x00,
                address_bus: 0x0000,
                read_mode: true,
            },
            address_input: "0000".to_string(),
            data_input: "00".to_string(),
            last_result: None,
        }
    }
}

impl eframe::App for RomGui {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            ui.heading("RomOnlyComputer");

            ui.horizontal(|ui| {
                ui.label("Address (hex):");
                ui.text_edit_singleline(&mut self.address_input);
            });

            ui.horizontal(|ui| {
                ui.label("Data (hex):");
                ui.text_edit_singleline(&mut self.data_input);
            });

            ui.checkbox(&mut self.computer.read_mode, "Read Mode");

            if ui.button("Tick").clicked() {
                if let (Ok(addr), Ok(data)) = (
                    u16::from_str_radix(&self.address_input.trim(), 16),
                    u8::from_str_radix(&self.data_input.trim(), 16),
                ) {
                    self.computer.address_bus = addr;
                    self.computer.data_bus = data;

                    let result = self.computer.rom.signal_tick(addr, data, true, true, true);
                    self.last_result = Some(result);

                    println!(
                        "Tick: A=${:04X} D=${:02X} R={} -> ${:02X}",
                        addr, data, self.computer.read_mode, result
                    );
                }
            }

            if let Some(result) = self.last_result {
                ui.label(format!("Last result: ${:02X}", result));
            }
        });
    }
}

fn main() -> eframe::Result<()> {
    let options = eframe::NativeOptions::default();
    eframe::run_native(
        "RomOnlyComputer GUI",
        options,
        Box::new(|_cc| Box::new(RomGui::default())),
    )
}
