// ----- Type Explanation -----
// StrLrg
// - StrLrg is a string type that is used to store a large string.
// - Char count [2 byte], String Data [2 byte * Char count],
// 
// - Stores a string with a maximum length of 65535 characters, supporting utf-16 characters.

// ----- Strucutre -----
#[derive(Clone, PartialEq, Eq)]
pub struct StrLrg {
    data: Vec<u8>,
}

// ----- Conversion: From -----

impl TryFrom<&str> for StrLrg {
    type Error = &'static str;

    fn try_from(value: &str) -> Result<Self, Self::Error> {
        // Encode the string into UTF-16 and collect into a Vec<u16>
        let utf16_encoded: Vec<u16> = value.encode_utf16().collect();
        let utf16_len = utf16_encoded.len();

        if utf16_len > 65535 {
            return Err("String is too long");
        }

        let mut data = Vec::with_capacity(2 + utf16_len * 2);
        data.extend((utf16_len as u16).to_le_bytes().iter());

        // Convert each u16 to little-endian bytes and extend the data vector
        for &code_unit in &utf16_encoded {
            data.extend(&code_unit.to_le_bytes());
        }

        Ok(Self { data })
    }
}

impl TryFrom<Vec<u8>> for StrLrg {
    type Error = &'static str;

    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
        if value.len() < 2 {
            return Err("Data too short to contain length");
        }

        if value.len() > 2 + 65535 * 2 {
            return Err("String is too long");
        }

        // Extract character count from the first two bytes
        let char_count = u16::from_le_bytes([value[0], value[1]]) as usize;
        let remaining_len = value.len() - 2;

        if char_count * 2 != remaining_len {
            return Err("Invalid string data");
        }

        Ok(Self { data: value })
    }
}

// ----- Conversion: To -----

impl StrLrg {
    pub fn to_string(&self) -> String {
        let char_count = u16::from_le_bytes([self.data[0], self.data[1]]) as usize;
        let mut utf16_data = Vec::with_capacity(char_count);

        for i in 0..char_count {
            let start = 2 + i * 2;


            let char_bytes: [u8; 2] = [self.data[start], self.data[start + 1]];
            let code_unit = u16::from_le_bytes(char_bytes);
            utf16_data.push(code_unit);
        }

        String::from_utf16(&utf16_data).unwrap()
    }

    pub fn to_vec(&self) -> Vec<u8> {
        self.data.clone()
    }
}

// ----- Getters -----

impl StrLrg {
    pub fn get_len(&self) -> usize {
        u16::from_le_bytes([self.data[0], self.data[1]]) as usize
    }

    pub fn get_bytecount(&self) -> usize {
        self.data.len()
    }
}

// ----- Byte Conversion -----
impl StrLrg {
    pub fn to_bytes(&self) -> &[u8] {
        &self.data
    }

    pub fn from_bytes(bytes: &[u8]) -> Self {
        Self { data: bytes.to_vec() }
    }
}

// ----- Display / Debug -----
use std::fmt;

impl fmt::Display for StrLrg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.to_string())
    }
}

impl fmt::Debug for StrLrg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "StrLrg: {}", self.to_string())
    }
}