use crate::aaml::AAML;
use crate::error::AamlError;
use crate::types::Type;

#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum MathTypes {
    Vector2,
    Vector3,
    Vector4,
    Quaternion,
    Matrix3x3,
    Matrix4x4,
}

impl Type for MathTypes {
    fn from_name(name: &str) -> Result<Self, AamlError>
    where
        Self: Sized,
    {
        match name {
            "vector2" => Ok(MathTypes::Vector2),
            "vector3" => Ok(MathTypes::Vector3),
            "vector4" => Ok(MathTypes::Vector4),
            "quaternion" => Ok(MathTypes::Quaternion),
            "matrix3x3" => Ok(MathTypes::Matrix3x3),
            "matrix4x4" => Ok(MathTypes::Matrix4x4),
            _ => Err(AamlError::NotFound(name.to_string())),
        }
    }

    fn base_type(&self) -> crate::types::primitive_type::PrimitiveType {
        crate::types::primitive_type::PrimitiveType::F64
    }

    fn validate(&self, value: &str, _aaml: &AAML) -> Result<(), AamlError> {
        let expected_len = match self {
            MathTypes::Vector2 => 2,
            MathTypes::Vector3 => 3,
            MathTypes::Vector4 | MathTypes::Quaternion => 4,
            MathTypes::Matrix3x3 => 9,
            MathTypes::Matrix4x4 => 16,
        };

        let mut count = 0usize;
        for part in value.split(',') {
            let part = part.trim();
            if part.parse::<f64>().is_err() {
                return Err(AamlError::InvalidValue(format!("Invalid number: {}", part)));
            }
            count += 1;
        }

        if count != expected_len {
            return Err(AamlError::InvalidValue(format!(
                "Expected {} components, got {}",
                expected_len, count
            )));
        }

        Ok(())
    }
}
