use std::time::Duration;

use crate::dbg_backend::{BackendCapability, DebugBackend, DebugCapability, StopEvent};
use crate::error::{Error, Result};
use crate::gdb::RegisterMap;
use crate::types::VirtAddr;

pub struct MemoryBackend {
    register_map: RegisterMap,
}

impl MemoryBackend {
    pub fn new() -> Self {
        Self {
            register_map: RegisterMap::default(),
        }
    }

    fn unsupported(operation: &str) -> Error {
        Error::DebugInfo(format!(
            "memory backend does not support {operation}; use KDCOM or gdb for target control"
        ))
    }
}

impl DebugBackend for MemoryBackend {
    fn register_map(&self) -> &RegisterMap {
        &self.register_map
    }

    fn capabilities(&self) -> Vec<BackendCapability> {
        vec![
            BackendCapability::supported(DebugCapability::MemoryIntrospection),
            BackendCapability::unsupported(DebugCapability::ExecutionControl),
            BackendCapability::unsupported(DebugCapability::InterruptTarget),
            BackendCapability::unsupported(DebugCapability::SingleStep),
            BackendCapability::unsupported(DebugCapability::ReadRegisters),
            BackendCapability::unsupported(DebugCapability::WriteRegisters),
            BackendCapability::unsupported(DebugCapability::ThreadList),
            BackendCapability::unsupported(DebugCapability::ThreadSelection),
            BackendCapability::unsupported(DebugCapability::KernelBreakpoints),
            BackendCapability::unsupported(DebugCapability::UserModeBreakpoints),
            BackendCapability::unsupported(DebugCapability::TargetReloadDetection),
            BackendCapability::unsupported(DebugCapability::KernelBaseHint),
            BackendCapability::unsupported(DebugCapability::BugcheckDetection),
            BackendCapability::unsupported(DebugCapability::BugcheckDetails),
            BackendCapability::unsupported(DebugCapability::DebugOutput),
        ]
    }

    fn read_registers(&mut self) -> Result<Vec<u8>> {
        Err(Self::unsupported("register reads"))
    }

    fn write_registers(&mut self, _data: &[u8]) -> Result<()> {
        Err(Self::unsupported("register writes"))
    }

    fn set_breakpoint(&mut self, _addr: u64) -> Result<()> {
        Err(Self::unsupported("kernel breakpoints"))
    }

    fn remove_breakpoint(&mut self, _addr: u64) -> Result<()> {
        Err(Self::unsupported("kernel breakpoints"))
    }

    fn continue_execution(&mut self) -> Result<()> {
        Err(Self::unsupported("continue"))
    }

    fn step(&mut self) -> Result<()> {
        Err(Self::unsupported("single-step"))
    }

    fn interrupt(&mut self) -> Result<StopEvent> {
        Err(Self::unsupported("target interrupt"))
    }

    fn wait_for_stop(&mut self) -> Result<StopEvent> {
        Err(Self::unsupported("waiting for target stops"))
    }

    fn try_wait_for_stop(&mut self, _timeout: Duration) -> Result<Option<StopEvent>> {
        Ok(None)
    }

    fn thread_list(&mut self) -> Result<Vec<String>> {
        Err(Self::unsupported("context enumeration"))
    }

    fn set_current_thread(&mut self, _thread_id: &str) -> Result<()> {
        Err(Self::unsupported("context selection"))
    }

    fn stopped_thread_id(&mut self) -> Result<String> {
        Err(Self::unsupported("stopped-context queries"))
    }

    fn target_kernel_base_hint(&mut self) -> Result<Option<VirtAddr>> {
        Ok(None)
    }

    fn is_running(&self) -> bool {
        true
    }
}
