use egui::{Button, CentralPanel, TextEdit, ViewportBuilder, ViewportId};
use winit::event_loop::EventLoopProxy;

use crate::{
    app::UserEvent,
    emulator::{EmulatorClient, SimId},
    gdbserver::{GdbServer, GdbServerStatus},
};

use super::AppWindow;

pub struct GdbServerWindow {
    sim_id: SimId,
    port_str: String,
    launched: bool,
    server: GdbServer,
    proxy: EventLoopProxy<UserEvent>,
}

impl GdbServerWindow {
    pub fn new(sim_id: SimId, client: EmulatorClient, proxy: EventLoopProxy<UserEvent>) -> Self {
        Self {
            sim_id,
            port_str: (8080 + sim_id.to_index()).to_string(),
            launched: false,
            server: GdbServer::new(sim_id, client),
            proxy,
        }
    }

    pub fn launch(&mut self, port: u16) {
        self.server.stop();
        self.port_str = port.to_string();
        self.launched = true;
        self.server.start(port);
    }
}

impl AppWindow for GdbServerWindow {
    fn viewport_id(&self) -> ViewportId {
        ViewportId::from_hash_of(format!("Debugger-{}", self.sim_id))
    }

    fn initial_viewport(&self) -> ViewportBuilder {
        ViewportBuilder::default()
            .with_title(format!("GDB Server ({})", self.sim_id))
            .with_inner_size((300.0, 200.0))
    }

    fn show(&mut self, ctx: &egui::Context) {
        let port_num: Option<u16> = self.port_str.parse().ok();
        let status = self.server.status();
        CentralPanel::default().show(ctx, |ui| {
            ui.horizontal(|ui| {
                if port_num.is_none() {
                    let style = ui.style_mut();
                    let error = style.visuals.error_fg_color;
                    style.visuals.widgets.active.bg_stroke.color = error;
                    style.visuals.widgets.hovered.bg_stroke.color = error;
                }
                ui.label("Port");
                let port_editor = TextEdit::singleline(&mut self.port_str).desired_width(100.0);
                ui.add_enabled(!status.running(), port_editor);
            });

            if !status.running() {
                if self.launched {
                    self.proxy.send_event(UserEvent::Quit).unwrap();
                }
                let start_button = Button::new("Start");
                if ui.add_enabled(port_num.is_some(), start_button).clicked() {
                    let port = port_num.unwrap();
                    self.server.start(port);
                }
            } else {
                let stop_button = Button::new("Stop");
                if ui.add(stop_button).clicked() {
                    self.server.stop();
                }
            }

            match &status {
                GdbServerStatus::Stopped => {}
                GdbServerStatus::Connecting => {
                    ui.label("Connecting...");
                }
                GdbServerStatus::Running => {
                    ui.label("Running");
                }
                GdbServerStatus::Error(message) => {
                    ui.label(message);
                }
            }
        });
    }
}