#[repr(C)]
#[derive(Debug, Clone, PartialEq)]
pub struct Vec2<T> {
    pub x: T,
    pub y: T
}

impl <T> Eq for Vec2<T> where T: PartialEq {}

impl <T> Vec2 <T> {
    #[inline]
    pub fn new(x: T, y: T) -> Self {
        Self { x, y }
    }

    pub fn as_ptr(&self) -> *const T {
        self as *const _ as *const T
    }

    pub fn as_mut_ptr(&mut self) -> *mut T {
        self as *mut _ as *mut T
    }

        ///
    /// ```
    /// use gfxmath_vec2::Vec2;
    /// 
    /// let a = Vec2::<f32>::new(1.0, 2.0);
    /// 
    /// let a_slice = a.as_slice();
    /// 
    /// assert_eq!(1.0, a_slice[0]);
    /// assert_eq!(2.0, a_slice[1]);
    /// ```
    pub fn as_slice(&self) -> &[T] {
        unsafe { std::slice::from_raw_parts(self.as_ptr(), 2) }
    }

    ///
    /// ```
    /// use gfxmath_vec2::Vec2;
    /// 
    /// let mut a = Vec2::<f32>::new(1.0, 2.0);
    /// 
    /// {
    ///     let a_slice = a.as_mut_slice();
    /// 
    ///     assert_eq!(1.0, a_slice[0]);
    ///     assert_eq!(2.0, a_slice[1]);
    /// 
    ///     a_slice[1] = 108.0;
    ///     assert_eq!(108.0, a_slice[1]); 
    /// }
    /// 
    /// a.x = 4.5;
    /// assert_eq!(4.5, a.x);
    /// 
    /// let a_slice = a.as_mut_slice();
    /// 
    /// assert_eq!(4.5, a_slice[0]);
    /// assert_eq!(108.0, a_slice[1]);
    /// ```
    pub fn as_mut_slice(&mut self) -> &mut [T] {
        unsafe { std::slice::from_raw_parts_mut(self.as_mut_ptr(), 2) }
    }
}

impl <T> Vec2<T> where T: Clone {
    /// ```
    /// use gfxmath_vec2::Vec2;
    /// 
    /// let v = Vec2::<f32>::all(2.5);
    /// 
    /// assert_eq!(2.5, v.x);
    /// assert_eq!(2.5, v.y);
    /// ```
    #[inline]
    pub fn all(val: T) -> Self {
        Self::new(val.clone(), val.clone())
    }
}

///
/// ```
/// use gfxmath_vec2::Vec2;
/// 
/// let v: Vec2<f32> = (3.0, 2.0).into();
/// 
/// assert_eq!(3.0, v.x);
/// assert_eq!(2.0, v.y);
/// ```
impl <T> From<(T, T)> for Vec2<T> {
    fn from(val: (T, T)) -> Self {
        Vec2::new(val.0, val.1)
    }
}

///
/// ```
/// use gfxmath_vec2::Vec2;
/// 
/// let v0 = (3.0, 2.0);
/// 
/// let v: Vec2<f32> = (&v0).into();
/// 
/// assert_eq!(3.0, v.x);
/// assert_eq!(2.0, v.y);
/// ```
impl <T> From<&(T, T)> for Vec2<T> where T: Clone {
    fn from(val: &(T, T)) -> Self {
        Vec2::new(val.0.clone(), val.1.clone())
    }
}

///
/// ```
/// use gfxmath_vec2::Vec2;
/// 
/// let v = Vec2::new(3.0, 2.0);
/// let v: (f32, f32) = v.into();
/// 
/// assert_eq!(3.0, v.0);
/// assert_eq!(2.0, v.1);
/// 
/// ```
impl <T> From<Vec2<T>> for (T, T) {
    fn from(val: Vec2<T>) -> Self {
        (val.x, val.y)
    }
}

///
/// ```
/// use gfxmath_vec2::Vec2;
/// 
/// let v = Vec2::new(3.0, 2.0);
/// let v: (f32, f32) = (&v).into();
/// 
/// assert_eq!(3.0, v.0);
/// assert_eq!(2.0, v.1);
/// ```
impl <T> From<&Vec2<T>> for (T, T) where T: Clone {
    fn from(val: &Vec2<T>) -> Self {
        (val.x.clone(), val.y.clone())
    }
}
