// ----- Type Explanation -----
// StrMinStatic
// - StrMinStatic is a string type that stores small strings efficiently using a fixed-size array.
// - Structure: [Char Count (1 byte), Char Set (1 byte), String Data (255 bytes)]
//
// - Stores a string with a maximum length of 255 characters, supporting ASCII characters.
// - The first byte stores the character count, and the second byte is reserved for character set.

use std::convert::TryFrom;
use std::fmt;

// ----- Structure -----
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct StrMinStatic {
    data: [u8; 257],
}

// ----- Conversion: From -----
impl TryFrom<&str> for StrMinStatic {
    type Error = &'static str;

    fn try_from(value: &str) -> Result<Self, Self::Error> {
        // Ensure the string does not exceed 255 bytes
        let bytes = value.as_bytes();
        if bytes.len() > 255 {
            return Err("String is too long. Maximum 255 bytes allowed.");
        }

        // Ensure all characters are ASCII
        if !value.is_ascii() {
            return Err("Non-ASCII characters detected. StrMinStatic supports only ASCII characters.");
        }

        let mut data = [0u8; 257];
        // Store the character count in the first byte
        data[0] = bytes.len() as u8;
        // Store the character set in the second byte (currently unused)
        data[1] = 0; // Placeholder for character set
        data[2..2 + bytes.len()].copy_from_slice(bytes);

        Ok(Self { data })
    }
}

// ----- Conversion: To -----
impl StrMinStatic {
    pub fn to_string(&self) -> String {
        // Read the character count from the first byte
        let length = self.data[0] as usize;

        // Extract the relevant slice and convert to String
        String::from_utf8(self.data[2..2 + length].to_vec())
            .expect("Invalid UTF-8 data in StrMinStatic")
    }

    /// Returns a Vec<u8> containing the used bytes (excluding trailing nulls).
    pub fn to_vec(&self) -> Vec<u8> {
        let length = self.data[0] as usize;
        self.data[2..2 + length].to_vec()
    }
}

// ----- Getters -----
impl StrMinStatic {
    /// Returns the total byte count (always 257).
    pub fn get_bytecount(&self) -> usize {
        self.data.len()
    }

    /// Returns the length of the stored string.
    pub fn get_length(&self) -> usize {
        self.data[0] as usize
    }
}

// ----- Byte Conversion -----
impl StrMinStatic {
    /// Returns a reference to the internal byte array.
    pub fn to_bytes(&self) -> &[u8; 257] {
        &self.data
    }

    pub fn from_bytes(bytes: &[u8; 257]) -> Result<Self, &'static str> {
        // Ensure the character count is valid
        let length = bytes[0] as usize;
        if length > 255 {
            return Err("Invalid length detected. Maximum 255 bytes allowed.");
        }

        // Ensure all bytes up to the length are ASCII
        if !bytes[2..2 + length].iter().all(|&b| b.is_ascii()) {
            return Err("Non-ASCII bytes detected. StrMinStatic supports only ASCII characters.");
        }

        Ok(Self { data: *bytes })
    }
}

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

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