use super::{
    bus::{bus_manager, Bus},
    Device, DeviceMatchName, DeviceMatcher, IdTable,
};
use crate::{
    driver::base::{
        device::{bus::BusNotifyEvent, dd::DeviceAttrCoredump, device_manager},
        kobject::KObject,
    },
    filesystem::sysfs::{sysfs_instance, Attribute, AttributeGroup},
};
use alloc::{
    string::ToString,
    sync::{Arc, Weak},
    vec::Vec,
};
use core::fmt::Debug;
use log::error;
use system_error::SystemError;

/// @brief: Driver error
#[allow(dead_code)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum DriverError {
    ProbeError,            // 探测设备失败(该驱动不能初始化这个设备)
    RegisterError,         // 设备注册失败
    AllocateResourceError, // 获取设备所需资源失败
    UnsupportedOperation,  // 不支持的操作
    UnInitialized,         // 未初始化
}

impl From<DriverError> for SystemError {
    fn from(value: DriverError) -> Self {
        match value {
            DriverError::ProbeError => SystemError::ENODEV,
            DriverError::RegisterError => SystemError::ENODEV,
            DriverError::AllocateResourceError => SystemError::EIO,
            DriverError::UnsupportedOperation => SystemError::EIO,
            DriverError::UnInitialized => SystemError::ENODEV,
        }
    }
}

#[inline(always)]
pub fn driver_manager() -> &'static DriverManager {
    &DriverManager
}

/// 驱动程序应当实现的trait
///
/// ## 注意
///
/// 由于设备驱动模型需要从Arc<dyn KObject>转换为Arc<dyn Driver>，
/// 因此，所有的实现了 Driver trait的结构体，都应该在结构体上方标注`#[cast_to([sync] Driver)]`，
/// 否则在运行时会报错
pub trait Driver: Sync + Send + Debug + KObject {
    fn coredump(&self, _device: &Arc<dyn Device>) -> Result<(), SystemError> {
        Err(SystemError::ENOSYS)
    }

    /// @brief: 获取驱动标识符
    /// @parameter: None
    /// @return: 该驱动驱动唯一标识符
    fn id_table(&self) -> Option<IdTable>;

    fn devices(&self) -> Vec<Arc<dyn Device>>;

    /// 把设备加入当前驱动管理的列表中
    fn add_device(&self, device: Arc<dyn Device>);

    /// 从当前驱动管理的列表中删除设备
    fn delete_device(&self, device: &Arc<dyn Device>);

    /// 根据设备名称查找绑定到驱动的设备
    ///
    /// 该方法是一个快速查找方法，要求驱动开发者自行实现。
    ///
    /// 如果开发者没有实现该方法，则应当返回None
    ///
    /// ## 注意
    ///
    /// 这是一个内部方法，不应当被外部调用，若要查找设备，请使用`find_device_by_name()`
    fn __find_device_by_name_fast(&self, _name: &str) -> Option<Arc<dyn Device>> {
        None
    }

    /// 是否禁用sysfs的bind/unbind属性
    ///
    /// ## 返回
    ///
    /// - true: 禁用
    /// - false: 不禁用（默认）
    fn suppress_bind_attrs(&self) -> bool {
        false
    }

    fn bus(&self) -> Option<Weak<dyn Bus>> {
        None
    }

    fn set_bus(&self, bus: Option<Weak<dyn Bus>>);

    fn groups(&self) -> &'static [&'static dyn AttributeGroup] {
        &[]
    }

    fn dev_groups(&self) -> &'static [&'static dyn AttributeGroup] {
        &[]
    }

    /// 使用什么样的策略来探测设备
    fn probe_type(&self) -> DriverProbeType {
        DriverProbeType::DefaultStrategy
    }
}

#[derive(Debug, Default)]
pub struct DriverCommonData {
    pub devices: Vec<Arc<dyn Device>>,
    pub bus: Option<Weak<dyn Bus>>,
}

impl DriverCommonData {
    pub fn push_device(&mut self, device: Arc<dyn Device>) {
        if !self.devices.iter().any(|d| Arc::ptr_eq(d, &device)) {
            self.devices.push(device);
        }
    }

    pub fn delete_device(&mut self, device: &Arc<dyn Device>) {
        self.devices.retain(|d| !Arc::ptr_eq(d, device));
    }
}

impl dyn Driver {
    pub fn allows_async_probing(&self) -> bool {
        match self.probe_type() {
            DriverProbeType::PreferAsync => true,
            DriverProbeType::ForceSync => false,
            DriverProbeType::DefaultStrategy => {
                // todo: 判断是否请求异步探测，如果是的话，就返回true

                // 由于目前还没有支持异步探测，因此这里暂时返回false
                false
            }
        }
    }

    /// 根据条件寻找一个绑定到这个驱动的设备(低效实现)
    ///
    /// ## 参数
    ///
    /// - `matcher` - 匹配器
    /// - `data` - 传给匹配器的数据
    ///
    /// ## 注意
    ///
    /// 这里的默认实现很低效，请为特定的驱动自行实现高效的查询
    fn find_device_slow<T: Copy>(
        &self,
        matcher: &dyn DeviceMatcher<T>,
        data: T,
    ) -> Option<Arc<dyn Device>> {
        self.devices()
            .into_iter()
            .find(|dev| matcher.match_device(dev, data))
    }

    /// 根据设备名称查找绑定到驱动的设备
    ///
    /// ## 注意
    ///
    /// 这里的默认实现很低效，请为特定的驱动自行实现高效的查询
    pub fn find_device_by_name(&self, name: &str) -> Option<Arc<dyn Device>> {
        if let Some(r) = self.__find_device_by_name_fast(name) {
            return Some(r);
        }

        return self.find_device_slow(&DeviceMatchName, name);
    }
}

/// @brief: 驱动管理器
#[derive(Debug, Clone)]
pub struct DriverManager;

impl DriverManager {
    /// 注册设备驱动。该设备驱动应当已经设置好其bus字段
    ///
    /// ## 参数
    ///
    /// - driver: 驱动
    ///
    /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/driver.c#222
    pub fn register(&self, driver: Arc<dyn Driver>) -> Result<(), SystemError> {
        let bus = driver.bus().and_then(|bus| bus.upgrade()).ok_or_else(|| {
            error!(
                "DriverManager::register() failed: driver.bus() is None. Driver: '{:?}'",
                driver.name()
            );
            SystemError::EINVAL
        })?;

        let drv_name = driver.name();
        let other = bus.find_driver_by_name(&drv_name);
        if other.is_some() {
            error!(
                "DriverManager::register() failed: driver '{}' already registered",
                drv_name
            );
            return Err(SystemError::EBUSY);
        }

        bus_manager().add_driver(&driver)?;

        self.add_groups(&driver, driver.groups())
            .inspect_err(|_e| {
                bus_manager().remove_driver(&driver);
            })?;

        // todo: 发送uevent

        return Ok(());
    }

    /// 从系统中删除一个驱动程序
    #[allow(dead_code)]
    pub fn unregister(&self, driver: &Arc<dyn Driver>) {
        self.remove_groups(driver, driver.groups());
        bus_manager().remove_driver(driver);
    }

    /// 参考： https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/base/dd.c#434
    pub fn driver_sysfs_add(&self, dev: &Arc<dyn Device>) -> Result<(), SystemError> {
        if let Some(bus) = dev.bus().and_then(|bus| bus.upgrade()) {
            bus.subsystem()
                .bus_notifier()
                .call_chain(BusNotifyEvent::BindDriver, Some(dev), None);
        }
        let driver_kobj = dev.driver().unwrap() as Arc<dyn KObject>;
        let device_kobj = dev.clone() as Arc<dyn KObject>;

        let err_remove_device = |e| {
            sysfs_instance().remove_link(&driver_kobj, dev.name());
            Err(e)
        };

        let err_remove_driver = |e| {
            sysfs_instance().remove_link(&device_kobj, "driver".to_string());
            err_remove_device(e)
        };

        sysfs_instance().create_link(Some(&driver_kobj), &device_kobj, device_kobj.name())?;

        if let Err(e) =
            sysfs_instance().create_link(Some(&device_kobj), &driver_kobj, "driver".to_string())
        {
            return err_remove_device(e);
        }

        if let Err(e) = device_manager().create_file(dev, &DeviceAttrCoredump) {
            return err_remove_driver(e);
        }

        return Ok(());
    }

    pub fn add_groups(
        &self,
        driver: &Arc<dyn Driver>,
        groups: &'static [&dyn AttributeGroup],
    ) -> Result<(), SystemError> {
        let kobj = driver.clone() as Arc<dyn KObject>;
        return sysfs_instance().create_groups(&kobj, groups);
    }

    pub fn remove_groups(&self, driver: &Arc<dyn Driver>, groups: &'static [&dyn AttributeGroup]) {
        let kobj = driver.clone() as Arc<dyn KObject>;
        sysfs_instance().remove_groups(&kobj, groups);
    }

    /// 为指定的驱动创建一个属性文件
    ///
    /// ## 参数
    ///
    /// - `driver` 要创建属性文件的驱动
    /// - `attr` 属性
    pub fn create_attr_file(
        &self,
        driver: &Arc<dyn Driver>,
        attr: &'static dyn Attribute,
    ) -> Result<(), SystemError> {
        let kobj = driver.clone() as Arc<dyn KObject>;
        return sysfs_instance().create_file(&kobj, attr);
    }

    /// 为指定的驱动删除一个属性文件
    ///
    /// 如果属性不存在,也不会报错
    ///
    /// ## 参数
    ///
    /// - `driver` 要删除属性文件的驱动
    /// - `attr` 属性
    pub fn remove_attr_file(&self, driver: &Arc<dyn Driver>, attr: &'static dyn Attribute) {
        let kobj = driver.clone() as Arc<dyn KObject>;
        sysfs_instance().remove_file(&kobj, attr);
    }
}

/// 驱动匹配器
///
/// 用于匹配驱动是否符合某个条件
///
/// ## 参数
///
/// - `T` - 匹配器的数据类型
/// - `data` - 匹配器的数据
pub trait DriverMatcher<T>: Debug {
    fn match_driver(&self, driver: &Arc<dyn Driver>, data: T) -> bool;
}

/// 根据名称匹配驱动
#[derive(Debug)]
pub struct DriverMatchName;

impl DriverMatcher<&str> for DriverMatchName {
    #[inline(always)]
    fn match_driver(&self, driver: &Arc<dyn Driver>, data: &str) -> bool {
        driver.name() == data
    }
}

/// enum probe_type - device driver probe type to try
/// Device drivers may opt in for special handling of their
/// respective probe routines. This tells the core what to
/// expect and prefer.
///
/// Note that the end goal is to switch the kernel to use asynchronous
/// probing by default, so annotating drivers with
/// %PROBE_PREFER_ASYNCHRONOUS is a temporary measure that allows us
/// to speed up boot process while we are validating the rest of the
/// drivers.
#[allow(dead_code)]
#[derive(Debug, Default)]
pub enum DriverProbeType {
    /// Drivers for "slow" devices which
    /// probing order is not essential for booting the system may
    /// opt into executing their probes asynchronously.
    PreferAsync,

    /// Use this to annotate drivers that need
    /// their probe routines to run synchronously with driver and
    /// device registration (with the exception of -EPROBE_DEFER
    /// handling - re-probing always ends up being done asynchronously).
    ForceSync,

    #[default]
    /// Used by drivers that work equally well
    /// whether probed synchronously or asynchronously.
    DefaultStrategy,
}
