//! 错误类型定义
//!
//! 提供 DarraError 和 Result 类型，用于安全封装层的错误处理。

use std::fmt;

/// Darra EtherCAT 错误类型
#[derive(Debug, Clone)]
pub enum DarraError {
    /// 主站已初始化
    AlreadyInitialized,
    /// 主站未初始化
    NotInitialized,
    /// 操作超时
    Timeout,
    /// 未发现从站
    NoSlaves,
    /// 网络配置失败 (返回码)
    NetworkFailed(i32),
    /// 状态切换失败 (目标状态)
    StateChangeFailed(u8),
    /// SDO 读取失败 (index, subindex)
    SdoReadFailed { index: u16, subindex: u8 },
    /// SDO 写入失败 (index, subindex)
    SdoWriteFailed { index: u16, subindex: u8 },
    /// SoE 操作失败 (IDN)
    SoeFailed(u16),
    /// FoE 操作失败 (文件名)
    FoeFailed(String),
    /// EoE 操作失败
    EoeFailed,
    /// AoE 操作失败
    AoeFailed,
    /// VoE 操作失败
    VoeFailed,
    /// 无效参数
    InvalidParameter(String),
    /// 配置加载失败
    ConfigLoadFailed(i32),
    /// 空指针 (DLL 返回 null)
    NullPointer,
    /// CiA 402 操作失败
    CiA402Failed(String),
    /// EMCY 操作失败
    EmcyFailed,
    /// PDO 操作失败
    PdoFailed(String),
    /// 拓扑操作失败
    TopologyFailed,
    /// 冗余操作失败
    RedundancyFailed,
    /// 寄存器操作失败
    RegisterFailed,
    /// 诊断操作失败
    DiagnosticsFailed,
    /// WDK 操作失败
    WdkFailed(String),
    /// UDP 操作失败
    UdpFailed,
    /// 其他错误
    Other(String),
}

impl fmt::Display for DarraError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::AlreadyInitialized => write!(f, "主站已初始化"),
            Self::NotInitialized => write!(f, "主站未初始化"),
            Self::Timeout => write!(f, "操作超时"),
            Self::NoSlaves => write!(f, "未发现从站"),
            Self::NetworkFailed(code) => write!(f, "网络配置失败 (返回码: {})", code),
            Self::StateChangeFailed(state) => write!(f, "状态切换失败 (目标: 0x{:02X})", state),
            Self::SdoReadFailed { index, subindex } => {
                write!(f, "SDO 读取失败 (0x{:04X}:{:02X})", index, subindex)
            }
            Self::SdoWriteFailed { index, subindex } => {
                write!(f, "SDO 写入失败 (0x{:04X}:{:02X})", index, subindex)
            }
            Self::SoeFailed(idn) => write!(f, "SoE 操作失败 (IDN: 0x{:04X})", idn),
            Self::FoeFailed(name) => write!(f, "FoE 操作失败 (文件: {})", name),
            Self::EoeFailed => write!(f, "EoE 操作失败"),
            Self::AoeFailed => write!(f, "AoE 操作失败"),
            Self::VoeFailed => write!(f, "VoE 操作失败"),
            Self::InvalidParameter(msg) => write!(f, "无效参数: {}", msg),
            Self::ConfigLoadFailed(code) => write!(f, "配置加载失败 (返回码: {})", code),
            Self::NullPointer => write!(f, "DLL 返回空指针"),
            Self::CiA402Failed(msg) => write!(f, "CiA 402 操作失败: {}", msg),
            Self::EmcyFailed => write!(f, "EMCY 操作失败"),
            Self::PdoFailed(msg) => write!(f, "PDO 操作失败: {}", msg),
            Self::TopologyFailed => write!(f, "拓扑操作失败"),
            Self::RedundancyFailed => write!(f, "冗余操作失败"),
            Self::RegisterFailed => write!(f, "寄存器操作失败"),
            Self::DiagnosticsFailed => write!(f, "诊断操作失败"),
            Self::WdkFailed(msg) => write!(f, "WDK 操作失败: {}", msg),
            Self::UdpFailed => write!(f, "UDP 操作失败"),
            Self::Other(msg) => write!(f, "{}", msg),
        }
    }
}

impl std::error::Error for DarraError {}

/// Darra EtherCAT 结果类型
pub type Result<T> = std::result::Result<T, DarraError>;

/// EtherCAT 从站状态
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum EcState {
    /// 无状态
    None = 0x00,
    /// Init 状态
    Init = 0x01,
    /// PreOp 状态
    PreOp = 0x02,
    /// Boot 状态
    Boot = 0x03,
    /// SafeOp 状态
    SafeOp = 0x04,
    /// OP 状态
    Operational = 0x08,
}

impl EcState {
    /// 从原始 u8 值创建 EcState
    pub fn from_raw(val: u8) -> Option<Self> {
        // 取低4位 (忽略 Error/Ack 标志 0x10)
        match val & 0x0F {
            0x00 => Some(Self::None),
            0x01 => Some(Self::Init),
            0x02 => Some(Self::PreOp),
            0x03 => Some(Self::Boot),
            0x04 => Some(Self::SafeOp),
            0x08 => Some(Self::Operational),
            _ => None,
        }
    }

    /// 检查状态值是否包含 Error 标志 (0x10)
    pub fn has_error(raw: u8) -> bool {
        (raw & 0x10) != 0
    }

    /// 格式化状态为可读字符串 (支持复合状态如 SafeOp+Error)
    pub fn format(raw: u8) -> String {
        let base = match raw & 0x0F {
            0x00 => "None",
            0x01 => "Init",
            0x02 => "PreOp",
            0x03 => "Boot",
            0x04 => "SafeOp",
            0x08 => "OP",
            _ => "Unknown",
        };
        if (raw & 0x10) != 0 {
            format!("{}+Error", base)
        } else {
            base.to_string()
        }
    }
}

impl fmt::Display for EcState {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let name = match self {
            Self::None => "None",
            Self::Init => "Init",
            Self::PreOp => "PreOp",
            Self::Boot => "Boot",
            Self::SafeOp => "SafeOp",
            Self::Operational => "OP",
        };
        write!(f, "{}", name)
    }
}

/// CiA 402 驱动器状态
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)]
pub enum CiA402State {
    /// 未就绪
    NotReady = 0,
    /// 等待上电
    SwitchOnDisabled = 1,
    /// 准备就绪
    ReadyToSwitchOn = 2,
    /// 已上电
    SwitchedOn = 3,
    /// 运行中
    OperationEnabled = 4,
    /// 快速停止
    QuickStopActive = 5,
    /// 故障反应
    FaultReaction = 6,
    /// 故障
    Fault = 7,
    /// 未知
    Unknown = 99,
}

impl CiA402State {
    /// 从原始 i32 值创建
    pub fn from_raw(val: i32) -> Self {
        match val {
            0 => Self::NotReady,
            1 => Self::SwitchOnDisabled,
            2 => Self::ReadyToSwitchOn,
            3 => Self::SwitchedOn,
            4 => Self::OperationEnabled,
            5 => Self::QuickStopActive,
            6 => Self::FaultReaction,
            7 => Self::Fault,
            _ => Self::Unknown,
        }
    }
}

/// CiA 402 运行模式
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i8)]
pub enum CiA402Mode {
    /// 位置规划模式
    PP = 1,
    /// 速度模式
    VL = 2,
    /// 轮廓速度模式
    PV = 3,
    /// 力矩模式
    PT = 4,
    /// 回零模式
    HM = 6,
    /// 插补位置模式
    IP = 7,
    /// 循环同步位置模式
    CSP = 8,
    /// 循环同步速度模式
    CSV = 9,
    /// 循环同步力矩模式
    CST = 10,
}

/// 链路状态
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum LinkState {
    /// 无连接
    Disconnected = 0,
    /// 链路正常
    Connected = 1,
    /// 冗余链路激活
    Redundancy = 2,
    /// 仅主网口连接
    PrimaryOnly = 3,
    /// 仅冗余网口连接
    SecondaryOnly = 4,
}

impl LinkState {
    /// 从原始值创建
    pub fn from_raw(val: u8) -> Self {
        match val {
            0 => Self::Disconnected,
            1 => Self::Connected,
            2 => Self::Redundancy,
            3 => Self::PrimaryOnly,
            4 => Self::SecondaryOnly,
            _ => Self::Disconnected,
        }
    }
}

/// 冗余状态枚举
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)]
pub enum RedundancyState {
    /// 无冗余
    None = 0,
    /// 仅主链路
    Primary = 1,
    /// 仅副链路
    Secondary = 2,
    /// 双链路均在线
    Both = 3,
}

impl RedundancyState {
    /// 从原始 i32 值创建
    pub fn from_raw(val: i32) -> Self {
        match val {
            0 => Self::None,
            1 => Self::Primary,
            2 => Self::Secondary,
            3 => Self::Both,
            _ => Self::None,
        }
    }
}

/// FoE 错误码 (ETG.1000.6 Table 92)
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
pub enum FoEErrorCode {
    /// 未定义错误
    NotDefined       = 0x8000,
    /// 文件未找到
    NotFound         = 0x8001,
    /// 访问被拒绝
    AccessDenied     = 0x8002,
    /// 磁盘满
    DiskFull         = 0x8003,
    /// 非法操作
    Illegal          = 0x8004,
    /// 数据包编号错误
    PacketNumberWrong = 0x8005,
    /// 文件已存在
    AlreadyExists    = 0x8006,
    /// 用户不存在
    NoUser           = 0x8007,
    /// 仅限Bootstrap模式
    BootstrapOnly    = 0x8008,
    /// 非Bootstrap模式
    NotBootstrap     = 0x8009,
    /// 无权限
    NoRights         = 0x800A,
    /// 程序错误
    ProgramError     = 0x800B,
}

impl FoEErrorCode {
    /// 将DLL错误码映射到FoE错误码
    pub fn from_dll_error(dll_error_code: i32) -> Self {
        let abs_code = dll_error_code.unsigned_abs();
        match abs_code {
            7  => FoEErrorCode::PacketNumberWrong, // EC_ERR_TYPE_FOE_PACKETNUMBER
            10 => FoEErrorCode::NotFound,
            12 => FoEErrorCode::AccessDenied,
            13 => FoEErrorCode::DiskFull,
            14 => FoEErrorCode::Illegal,
            15 => FoEErrorCode::PacketNumberWrong,
            16 => FoEErrorCode::AlreadyExists,
            17 => FoEErrorCode::NoUser,
            18 => FoEErrorCode::BootstrapOnly,
            19 => FoEErrorCode::NotBootstrap,
            20 => FoEErrorCode::NoRights,
            21 => FoEErrorCode::ProgramError,
            _ => FoEErrorCode::NotDefined,
        }
    }
}

/// SoE 错误码 (ETG.5003)
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
pub enum SoEErrorCode {
    /// 无错误
    NoError = 0x0000,
    /// 无此IDN
    NoIDN = 0x1001,
    /// 无效的元素访问
    InvalidAccessToElement = 0x1009,
    /// 无名称
    NoName = 0x2001,
    /// 名称传输太短
    NameTransmissionTooShort = 0x2002,
    /// 名称传输太长
    NameTransmissionTooLong = 0x2003,
    /// 名称不可更改
    NameCannotBeChanged = 0x2004,
    /// 名称写保护
    NameWriteProtected = 0x2005,
    /// 属性传输太短
    AttributeTransmissionTooShort = 0x3002,
    /// 属性传输太长
    AttributeTransmissionTooLong = 0x3003,
    /// 属性不可更改
    AttributeCannotBeChanged = 0x3004,
    /// 属性写保护
    AttributeWriteProtected = 0x3005,
    /// 无单位
    NoUnits = 0x4001,
    /// 单位传输太短
    UnitTransmissionTooShort = 0x4002,
    /// 单位传输太长
    UnitTransmissionTooLong = 0x4003,
    /// 单位不可更改
    UnitCannotBeChanged = 0x4004,
    /// 单位写保护
    UnitWriteProtected = 0x4005,
    /// 无最小输入值
    NoMinimumInputValue = 0x5001,
    /// 最小输入值传输太短
    MinValueTooShort = 0x5002,
    /// 最小输入值传输太长
    MinValueTooLong = 0x5003,
    /// 最小输入值不可更改
    MinValueCannotBeChanged = 0x5004,
    /// 最小输入值写保护
    MinValueWriteProtected = 0x5005,
    /// 无最大输入值
    NoMaximumInputValue = 0x6001,
    /// 最大输入值传输太短
    MaxValueTooShort = 0x6002,
    /// 最大输入值传输太长
    MaxValueTooLong = 0x6003,
    /// 最大输入值不可更改
    MaxValueCannotBeChanged = 0x6004,
    /// 最大输入值写保护
    MaxValueWriteProtected = 0x6005,
    /// 无操作数据
    NoOperationData = 0x7001,
    /// 操作数据太短
    OpDataTooShort = 0x7002,
    /// 操作数据太长
    OpDataTooLong = 0x7003,
    /// 操作数据不可更改
    OpDataCannotBeChanged = 0x7004,
    /// 操作数据写保护
    OpDataWriteProtected = 0x7005,
    /// 操作数据小于最小值
    OpDataSmallerThanMin = 0x7006,
    /// 操作数据大于最大值
    OpDataGreaterThanMax = 0x7007,
    /// 无效的驱动器号
    InvalidDriveNumber = 0x800A,
    /// 通用错误
    GeneralError = 0x800B,
    /// 未寻址任何元素
    NoElementAddressed = 0x800C,
    /// 未知错误
    Unknown = 0xFFFF,
}

/// DC 同步窗口状态
#[derive(Debug, Clone, Copy)]
pub struct SyncWindowStatus {
    /// 当前同步偏差 (ns)
    pub diff_ns: i32,
    /// 最大同步偏差 (ns)
    pub max_diff_ns: i32,
    /// 最小同步偏差 (ns)
    pub min_diff_ns: i32,
    /// 是否同步
    pub in_sync: bool,
    /// 失同步计数
    pub out_of_sync_count: u32,
}
