use crate::Exception;

/// Number system conversion tool
pub struct HexUtil;

impl HexUtil {
    /// 将字节数组转换为十六进制字符串表示
    ///
    /// # 参数
    /// * `bytes` - 需要转换的字节切片
    ///
    /// # 返回值
    /// 返回表示输入字节的十六进制字符串，每个字节用两个十六进制字符表示
    pub fn to_hex(bytes: &[u8]) -> String {
        let mut hex_str = String::new();
        // 遍历每个字节并转换为十六进制格式
        for byte in bytes {
            hex_str += &format!("{:02x}", byte);
        }
        hex_str
    }

    pub fn to_bytes(hex: &str) -> Result<Vec<u8>, Exception> {
        // 检查十六进制字符串长度是否为偶数
        if hex.len() % 2 != 0 {
            return Err(Exception::ParseError("Invalid hex string length".to_string()));
        }
        let mut bytes = Vec::with_capacity(hex.len() / 2);
        let mut chars = hex.chars();
        // 按两个字符一组解析十六进制字节
        while let (Some(a), Some(b)) = (chars.next(), chars.next()) {
            let byte = match u8::from_str_radix(&format!("{}{}", a, b), 16) {
                Ok(byte) => byte,
                Err(_) => return Err(Exception::ParseError("Invalid hex digit".to_string())),
            };
            bytes.push(byte);
        }
        Ok(bytes)
    }

    /// 将字符串编码为十六进制字符串
    ///
    /// # 参数
    /// * `text` - 需要编码的原始字符串
    ///
    /// # 返回值
    /// 返回编码后的十六进制字符串
    pub fn encode_hex_str(text: &str) -> String {
        let bytes = text.as_bytes();
        let hex_str = HexUtil::to_hex(bytes);
        hex_str
    }

    /// 将十六进制字符串解码为UTF-8字符串
    ///
    /// # 参数
    /// * `hex` - 要解码的十六进制字符串引用
    ///
    /// # 返回值
    /// * `Ok(String)` - 解码成功的UTF-8字符串
    /// * `Err(&'static str)` - 解码失败时的错误信息，可能的错误包括：
    ///   - "Invalid hex string length"：十六进制字符串长度为奇数
    ///   - "Invalid hex digit"：包含无效的十六进制字符
    ///   - "Invalid UTF-8 sequence"：解码后的字节序列不是有效的UTF-8
    ///
    /// # 示例
    /// ```
    /// let result = decode_hex_str("48656c6c6f"); // 解码为 "Hello"
    /// ```
    pub fn decode_hex_str(hex: &str) -> Result<String, &'static str> {
        // 检查十六进制字符串长度是否为偶数
        if hex.len() % 2 != 0 {
            return Err("Invalid hex string length");
        }
        let mut bytes = Vec::with_capacity(hex.len() / 2);
        let mut chars = hex.chars();
        // 按两个字符一组解析十六进制字节
        while let (Some(a), Some(b)) = (chars.next(), chars.next()) {
            let byte = match u8::from_str_radix(&format!("{}{}", a, b), 16) {
                Ok(byte) => byte,
                Err(_) => return Err("Invalid hex digit"),
            };
            bytes.push(byte);
        }
        // 将字节序列转换为UTF-8字符串
        match str::from_utf8(&bytes) {
            Ok(s) => Ok(s.to_string()),
            Err(_) => Err("Invalid UTF - 8 sequence"),
        }
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_to_hex() {
        let hex_str = HexUtil::to_hex(&[0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]);
        println!("{}", hex_str);

        let bytes: Vec<u8> = "hello, rust!".bytes().collect();
        let hex_str = HexUtil::to_hex(&bytes);
        println!("{}", hex_str);

        let bytes = "hello, rust!".to_string().as_bytes().to_vec();
        let hex_str = HexUtil::to_hex(&bytes);
        println!("{}", hex_str);

        let str = String::from("hello, rust!");
        let bytes = str.as_bytes();
        let hex_str = HexUtil::to_hex(bytes);
        println!("{}", hex_str);
    }

    #[test]
    fn test_encode_decode_hex_str() {
        let origin = "hello, rust!";

        let hex_str = HexUtil::encode_hex_str(origin);
        println!("{}", hex_str);
        let decoded = HexUtil::decode_hex_str(&hex_str).unwrap();
        println!("{}", decoded);
        assert_eq!(origin, decoded);
    }
}
