use std::ops::{Add, Mul, Sub};

#[macro_export]
macro_rules! vec3 {
    ($x:expr, $y:expr, $z:expr) => {
        $crate::vector::Vector3 {
            x: $x,
            y: $y,
            z: $z,
        }
    };
}

#[derive(Debug, Default)]
pub struct Vector3<S> {
    pub x: S,
    pub y: S,
    pub z: S,
}

impl Into<Vector3<f32>> for Vector3<i32> {
    fn into(self) -> Vector3<f32> {
        Vector3 {
            x: self.x as f32,
            y: self.y as f32,
            z: self.z as f32,
        }
    }
}

impl<S: Clone> Clone for Vector3<S> {
    fn clone(&self) -> Self {
        Self {
            x: self.x.clone(),
            y: self.y.clone(),
            z: self.z.clone(),
        }
    }
}

impl<S: Copy> Copy for Vector3<S> {}

impl<S: Add<Output = S>> Add for Vector3<S> {
    type Output = Self;

    fn add(self, rhs: Self) -> Self::Output {
        Self {
            x: self.x + rhs.x,
            y: self.y + rhs.y,
            z: self.z + rhs.z,
        }
    }
}

impl<S: Sub<Output = S>> Sub for Vector3<S> {
    type Output = Self;

    fn sub(self, rhs: Self) -> Self::Output {
        Self {
            x: self.x - rhs.x,
            y: self.y - rhs.y,
            z: self.z - rhs.z,
        }
    }
}

impl<S: Mul<Output = S>> Mul for Vector3<S> {
    type Output = Self;

    fn mul(self, rhs: Self) -> Self::Output {
        Self {
            x: self.x * rhs.x,
            y: self.y * rhs.y,
            z: self.z * rhs.z,
        }
    }
}

impl<S: Mul<Output = S> + Copy> Mul<S> for Vector3<S> {
    type Output = Self;

    fn mul(self, rhs: S) -> Self::Output {
        Self {
            x: self.x * rhs,
            y: self.y * rhs,
            z: self.z * rhs,
        }
    }
}
