//! # Vec2
//!
//! 2-dimensional vector math for game-engine development and graphics.
//!
//! # Example
//!
//! ```rust
//! # use roofy::Vec2;
//! let player: Vec2 = Vec2::ZERO;
//! let target: Vec2 = Vec2::new(3.0, 4.0);
//!
//! let direction: Vec2 = (target - player).normalized();
//! let speed: f32 = 10.0;
//! let velocity: Vec2 = direction * speed;
//!
//! assert_eq!(direction, Vec2::new(0.6, 0.8));
//! assert_eq!(velocity, Vec2::new(6.0, 8.0));
//! ```
use std::{
    fmt::Display,
    iter::{Product, Sum},
    ops::{
        Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Rem, RemAssign, Sub,
        SubAssign,
    },
};

use crate::{Vec3, Vec4};

/// Creates a [`Vec2`](crate::Vec2) from components or a single splat value.
///
/// # Examples
/// ```rust
/// # use roofy::{Vec2, vec2};
/// // From 2 components
/// let v = vec2!(1.0, 2.0);
/// assert_eq!(v, Vec2::new(1.0, 2.0));
///
/// // From a single splat value
/// let v = vec2!(0.0);
/// assert_eq!(v, Vec2::ZERO);
///
/// // From Integer literals is accepted.
/// let v = vec2!(1, 2);
/// assert_eq!(v, Vec2::new(1.0, 2.0));
/// ```
#[macro_export]
macro_rules! vec2 {
    ($x:expr, $y:expr) => {
        $crate::Vec2::new($x as f32, $y as f32)
    };
    ($v:expr) => {
        $crate::Vec2::splat($v as f32)
    };
}

/// 2-dimensional vector, with `f32` components.
/// Same memory layout as `[f32; 2]`.
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(C)]
pub struct Vec2 {
    /// X component of the vector.
    pub x: f32,
    /// Y component of the vector.
    pub y: f32,
}

impl Vec2 {
    /// Threshold for treating a value as zero.
    pub const EPSILON: f32 = 1e-6;
    /// [`EPSILON`](Self::EPSILON) squared.
    pub const EPSILON_SQ: f32 = Self::EPSILON * Self::EPSILON;

    /// Shorthand for writing `Vec2::splat(0.0)`.
    pub const ZERO: Self = Self::splat(0.0);
    /// Shorthand for writing `Vec2::splat(1.0)`.
    pub const ONE: Self = Self::splat(1.0);
    /// Shorthand for writing `Vec2::splat(-1.0)`.
    pub const NEG_ONE: Self = Self::splat(-1.0);
    /// Shorthand for writing `Vec2::splat(f32::INFINITY)`.
    pub const INFINITY: Self = Self::splat(f32::INFINITY);
    /// Shorthand for writing `Vec2::splat(f32::NEG_INFINITY)`.
    pub const NEG_INFINITY: Self = Self::splat(f32::NEG_INFINITY);
    /// Shorthand for writing `Vec2::splat(f32::NAN)`.
    pub const NAN: Self = Self::splat(f32::NAN);

    /// Shorthand for writing `Vec2::new(1.0, 0.0)`.
    pub const X: Self = Self::new(1.0, 0.0);
    /// Shorthand for writing `Vec2::new(-1.0, 0.0)`.
    pub const NEG_X: Self = Self::new(-1.0, 0.0);
    /// Shorthand for writing `Vec2::new(0.0, 1.0)`.
    pub const Y: Self = Self::new(0.0, 1.0);
    /// Shorthand for writing `Vec2::new(0.0, -1.0)`.
    pub const NEG_Y: Self = Self::new(0.0, -1.0);

    /// Creates a `Vec2` with `x` and `y` components.
    #[inline(always)]
    #[must_use]
    pub const fn new(x: f32, y: f32) -> Self {
        Self { x, y }
    }

    /// Creates a `Vec2` with all components `v`.
    #[inline(always)]
    #[must_use]
    pub const fn splat(v: f32) -> Self {
        Self::new(v, v)
    }

    /// Creates a `Vec2` from `[x, y]`
    #[inline]
    #[must_use]
    pub const fn from_array(a: [f32; 2]) -> Self {
        Self::new(a[0], a[1])
    }

    /// Creates `[x, y]` from a `Vec2`.
    #[inline]
    #[must_use]
    pub const fn to_array(self) -> [f32; 2] {
        [self.x, self.y]
    }

    /// Creates a `Vec2` from first 2 values of `slice`.
    ///
    /// # Panics
    /// Panics if `slice` is less than 2 elements long.
    #[inline]
    #[must_use]
    pub const fn from_slice(slice: &[f32]) -> Self {
        Self::new(slice[0], slice[1])
    }

    /// Writes the components of `self` to the first 2 elements of `slice`.
    ///
    /// # Panics
    /// Panics if `slice` is less than 2 elements long.
    #[inline]
    pub fn write_to_slice(self, slice: &mut [f32]) {
        slice[0] = self.x;
        slice[1] = self.y;
    }

    /// Creates a `Vec2` from the `x` and `y` components of a `Vec3`, with `z` discarded.
    #[inline]
    #[must_use]
    pub const fn from_vec3(v: Vec3) -> Self {
        Self::new(v.x, v.y)
    }

    /// Creates a `Vec3` from a `Vec2`, with `z` set to `0.0`.
    ///
    /// Equivalent to [`from_vec2`](Vec3::from_vec2()).
    #[inline]
    #[must_use]
    pub const fn to_vec3(self) -> Vec3 {
        Vec3::from_vec2(self)
    }

    /// Creates a `Vec2` from the `x` and `y` components of a `Vec4`, with `z` and `w` discarded.
    #[inline]
    pub const fn from_vec4(v: Vec4) -> Self {
        Self::new(v.x, v.y)
    }

    /// Creates a `Vec4` from a `Vec2`, with `z` and `w` set to `0.0`.
    ///
    /// Equivalent to [`from_vec2`](Vec4::from_vec2()).
    #[inline]
    #[must_use]
    pub const fn to_vec4(self) -> Vec4 {
        Vec4::from_vec2(self)
    }

    /// Returns the component-wise sum of `self` and `rhs`.
    #[inline]
    #[must_use]
    pub const fn add(self, rhs: Self) -> Self {
        Self::new(self.x + rhs.x, self.y + rhs.y)
    }

    /// Sets `self` to the component-wise sum of `self` and `rhs`.
    #[inline]
    pub const fn add_assign(&mut self, rhs: Self) {
        self.x += rhs.x;
        self.y += rhs.y;
    }

    /// Returns `self` with `rhs` added to each component.
    #[inline]
    #[must_use]
    pub const fn add_scalar(self, rhs: f32) -> Self {
        Self::new(self.x + rhs, self.y + rhs)
    }

    /// Sets `self` to `self` with `rhs` added to each component.
    #[inline]
    pub const fn add_assign_scalar(&mut self, rhs: f32) {
        self.x += rhs;
        self.y += rhs;
    }

    /// Returns the component-wise difference of `self` and `rhs`.
    #[inline]
    #[must_use]
    pub const fn sub(self, rhs: Self) -> Self {
        Self::new(self.x - rhs.x, self.y - rhs.y)
    }

    /// Sets `self` to the component-wise difference of `self` and `rhs`.
    #[inline]
    pub const fn sub_assign(&mut self, rhs: Self) {
        self.x -= rhs.x;
        self.y -= rhs.y;
    }

    /// Returns `self` with `rhs` subtracted from each component.
    #[inline]
    #[must_use]
    pub const fn sub_scalar(self, rhs: f32) -> Self {
        Self::new(self.x - rhs, self.y - rhs)
    }

    /// Sets `self` to `self` with `rhs` subtracted from each component.
    #[inline]
    pub const fn sub_assign_scalar(&mut self, rhs: f32) {
        self.x -= rhs;
        self.y -= rhs;
    }

    /// Returns the component-wise product of `self` and `rhs`.
    #[inline]
    #[must_use]
    pub const fn mul(self, rhs: Self) -> Self {
        Self::new(self.x * rhs.x, self.y * rhs.y)
    }

    /// Sets `self` to the component-wise product of `self` and `rhs`.
    #[inline]
    pub const fn mul_assign(&mut self, rhs: Self) {
        self.x *= rhs.x;
        self.y *= rhs.y;
    }

    /// Returns `self` with each component multiplied by `rhs`.
    #[inline]
    #[must_use]
    pub const fn mul_scalar(self, rhs: f32) -> Self {
        Self::new(self.x * rhs, self.y * rhs)
    }

    /// Sets `self` to `self` with each component multiplied by `rhs`.
    #[inline]
    pub const fn mul_assign_scalar(&mut self, rhs: f32) {
        self.x *= rhs;
        self.y *= rhs;
    }

    /// Returns the component-wise quotient of `self` and `rhs`.
    #[inline]
    #[must_use]
    pub const fn div(self, rhs: Self) -> Self {
        Self::new(self.x / rhs.x, self.y / rhs.y)
    }

    /// Sets `self` to the component-wise quotient of `self` and `rhs`.
    #[inline]
    pub const fn div_assign(&mut self, rhs: Self) {
        self.x /= rhs.x;
        self.y /= rhs.y;
    }

    /// Returns `self` with each component divided by `rhs`.
    #[inline]
    #[must_use]
    pub const fn div_scalar(self, rhs: f32) -> Self {
        Self::new(self.x / rhs, self.y / rhs)
    }

    /// Sets `self` to `self` with each component divided by `rhs`.
    #[inline]
    pub const fn div_assign_scalar(&mut self, rhs: f32) {
        self.x /= rhs;
        self.y /= rhs;
    }

    /// Returns `self` with each component taken modulo `rhs`.
    #[inline]
    #[must_use]
    pub const fn rem(self, rhs: Self) -> Self {
        Self::new(self.x % rhs.x, self.y % rhs.y)
    }

    /// Sets `self` to `self` with each component taken modulo `rhs`.
    #[inline]
    pub const fn rem_assign(&mut self, rhs: Self) {
        self.x %= rhs.x;
        self.y %= rhs.y;
    }

    /// Returns `self` with each component taken modulo `rhs`.
    #[inline]
    #[must_use]
    pub const fn rem_scalar(self, rhs: f32) -> Self {
        Self::new(self.x % rhs, self.y % rhs)
    }

    /// Sets `self` to `self` with each component taken modulo `rhs`.
    #[inline]
    pub const fn rem_assign_scalar(&mut self, rhs: f32) {
        self.x %= rhs;
        self.y %= rhs;
    }

    /// Returns `self` with negated components.
    #[inline]
    #[must_use]
    pub const fn neg(self) -> Self {
        Self::new(-self.x, -self.y)
    }

    /// Returns a reference to the component at `index`.
    ///
    /// `0` maps to `x`, `1` maps to `y`.
    ///
    /// # Panics
    /// Panics if `index` is greater than `1`.
    #[inline]
    #[must_use]
    pub const fn index(&self, index: usize) -> &f32 {
        match index {
            0 => &self.x,
            1 => &self.y,
            _ => panic!("index out of bounds"),
        }
    }

    /// Returns a mutable reference to the component at `index`.
    ///
    /// `0` maps to `x`, `1` maps to `y`.
    ///
    /// # Panics
    /// Panics if `index` is greater than `1`.
    #[inline]
    #[must_use]
    pub const fn index_mut(&mut self, index: usize) -> &mut f32 {
        match index {
            0 => &mut self.x,
            1 => &mut self.y,
            _ => panic!("index out of bounds"),
        }
    }

    /// Returns a reference to the components as `[x, y]`.
    ///
    /// # Safety
    /// Relies on `Vec2` being `#[repr(C)]`
    #[inline]
    #[must_use]
    pub const fn as_ref(&self) -> &[f32; 2] {
        unsafe { &*(self as *const Vec2 as *const [f32; 2]) }
    }

    /// Returns a reference to the components as `[x, y]`.
    ///
    /// # Safety
    /// Relies on `Vec2` being `#[repr(C)]`
    #[inline]
    #[must_use]
    pub const fn as_mut(&mut self) -> &mut [f32; 2] {
        unsafe { &mut *(self as *mut Vec2 as *mut [f32; 2]) }
    }

    /// Returns `self` with `f` applied to each component.
    #[inline]
    #[must_use]
    pub fn map<F>(self, mut f: F) -> Self
    where
        F: FnMut(f32) -> f32,
    {
        Self::new(f(self.x), f(self.y))
    }

    /// Returns `self` with the `x` component set to `x`.
    #[inline]
    #[must_use]
    pub const fn with_x(self, x: f32) -> Self {
        Self::new(x, self.y)
    }

    /// Returns `self` with the `y` component set to `y`.
    #[inline]
    #[must_use]
    pub const fn with_y(self, y: f32) -> Self {
        Self::new(self.x, y)
    }

    /// Returns the dot product of `self` and `other`.
    #[inline]
    #[must_use]
    pub const fn dot(self, other: Self) -> f32 {
        self.x * other.x + self.y * other.y
    }

    /// Returns the length of `self`.
    #[inline]
    #[must_use]
    pub fn length(self) -> f32 {
        self.dot(self).sqrt()
    }

    /// Returns the squared length of `self`.
    #[inline]
    #[must_use]
    pub const fn length_squared(self) -> f32 {
        self.dot(self)
    }

    /// Normalizes `self`.
    ///
    /// # Preconditions
    /// Expects the length of `self` to not be approximately `0.0` and finite.
    #[inline]
    pub fn normalize(&mut self) {
        *self *= self.length().recip();
    }

    /// Returns `self` normalized.
    ///
    /// # Preconditions
    /// Expects the length of `self` to not be approximately `0.0` and finite.
    #[inline]
    #[must_use]
    pub fn normalized(self) -> Self {
        self * self.length().recip()
    }

    /// Returns `true` and normalizes `self` if the length of `self`
    /// is not approximately `0.0` and finite, otherwise leaves `self` unchanged
    /// and returns `false`.
    ///
    /// Uses [`EPSILON`](Self::EPSILON) as a threshold.
    #[inline]
    #[must_use]
    pub fn try_normalize(&mut self) -> bool {
        let len_sq: f32 = self.length_squared();

        if len_sq < Self::EPSILON_SQ || !len_sq.is_finite() {
            return false;
        }

        self.normalize();
        true
    }

    /// Returns `self` normalized if the length of `self` is not
    /// approximately `0.0` and finite, otherwise returns `None`.
    ///
    /// Uses [`EPSILON`](Self::EPSILON) as a threshold.
    #[inline]
    #[must_use]
    pub fn try_normalized(self) -> Option<Self> {
        let len_sq: f32 = self.length_squared();

        if len_sq < Self::EPSILON_SQ || !len_sq.is_finite() {
            return None;
        }

        Some(self.normalized())
    }

    /// Returns `self` normalized if the length of `self` is not
    /// approximately `0.0` and finite, otherwise returns `fallback`.
    ///
    /// Uses [`EPSILON`](Self::EPSILON) as a threshold.
    #[inline]
    #[must_use]
    pub fn normalized_or(self, fallback: Self) -> Self {
        self.try_normalized().unwrap_or(fallback)
    }

    /// Returns `self` normalized if the length of `self` is not
    /// approximately `0.0` and finite, otherwise returns [`ZERO`](Self::ZERO).
    ///
    /// Uses [`EPSILON`](Self::EPSILON) as a threshold.
    #[inline]
    #[must_use]
    pub fn normalized_or_zero(self) -> Self {
        self.normalized_or(Self::ZERO)
    }

    /// Returns `true` if the length of `self` is approximately `1.0`.
    ///
    /// Uses [`EPSILON`](Self::EPSILON) as a threshold.
    #[inline]
    #[must_use]
    pub const fn is_normalized(self) -> bool {
        (self.length_squared() - 1.0).abs() < Self::EPSILON
    }

    /// Returns a `Vec2` with direction of `self` and length clamped between `min_length` and `max_length`.
    ///
    /// # Preconditions
    /// Expects `min_length` to be non-negative and less than or equal to `max_length`.
    ///
    /// # Edge cases
    /// If `self` is near-zero, returns [`ZERO`](Self::ZERO).
    #[inline]
    #[must_use]
    pub fn clamp_length(self, min_length: f32, max_length: f32) -> Self {
        let len_sq: f32 = self.length_squared();

        if len_sq < Self::EPSILON_SQ {
            return Self::ZERO;
        }

        let len: f32 = len_sq.sqrt();
        let clamped: f32 = len.clamp(min_length, max_length);

        if clamped == len {
            return self;
        }

        self * (clamped / len)
    }

    /// Returns the angle between `self` and `to` in radians.
    ///
    /// # Edge cases
    /// If either vector is near-zero, returns `0.0`.
    #[inline]
    #[must_use]
    pub fn angle_between(self, to: Self) -> f32 {
        let len_sq: f32 = self.length_squared() * to.length_squared();

        if len_sq < Self::EPSILON_SQ {
            return 0.0;
        }

        (self.dot(to) / len_sq.sqrt()).clamp(-1.0, 1.0).acos()
    }

    /// Returns the angle between `self` and `to` in degrees.
    ///
    /// # Edge cases
    /// If either vector is near-zero, returns `0.0`.
    #[inline]
    #[must_use]
    pub fn angle_between_degrees(self, to: Self) -> f32 {
        self.angle_between(to).to_degrees()
    }

    /// Returns the distance from `self` to `to`.
    #[inline]
    #[must_use]
    pub fn distance(self, to: Self) -> f32 {
        (self - to).length()
    }

    /// Returns the distance squared from `self` to `to`.
    #[inline]
    #[must_use]
    pub const fn distance_squared(self, to: Self) -> f32 {
        (self.sub(to)).length_squared()
    }

    /// Returns a `Vec2` perpendicular to `self` (rotated 90 degrees counter-clockwise).
    #[inline]
    #[must_use]
    pub const fn perpendicular(self) -> Self {
        Self::new(-self.y, self.x)
    }

    /// Returns `self` reflected off `normal`.
    ///
    /// # Preconditions
    /// Expects `normal` to be normalized.
    #[inline]
    #[must_use]
    pub const fn reflect(self, normal: Self) -> Self {
        let factor: f32 = -2.0 * self.dot(normal);
        Self::new(factor * normal.x + self.x, factor * normal.y + self.y)
    }

    /// Returns a `Vec2` with the smallest components of `self` and `other`.
    #[inline]
    #[must_use]
    pub const fn min(self, other: Self) -> Self {
        Self::new(self.x.min(other.x), self.y.min(other.y))
    }

    /// Returns a `Vec2` with the largest components of `self` and `other`.
    #[inline]
    #[must_use]
    pub const fn max(self, other: Self) -> Self {
        Self::new(self.x.max(other.x), self.y.max(other.y))
    }

    /// Returns a `Vec2` with components of `self` clamped between corresponding components of `min` and `max`.
    ///
    /// # Preconditions
    /// Expects each component of `min` to be less than or equal to the corresponding component of `max`.
    #[inline]
    #[must_use]
    pub const fn clamp(self, min: Self, max: Self) -> Self {
        self.max(min).min(max)
    }

    /// Returns `self` with the absolute value of each component.
    #[inline]
    #[must_use]
    pub const fn abs(self) -> Self {
        Self::new(self.x.abs(), self.y.abs())
    }

    /// Returns `self` with the sign of each component.
    ///
    /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
    /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
    /// - `NaN`` if the number is `NaN`
    #[inline]
    #[must_use]
    pub const fn signum(self) -> Self {
        Self::new(self.x.signum(), self.y.signum())
    }

    /// Returns `self` with each component raised to the power of `n`.
    #[inline]
    #[must_use]
    pub fn powf(self, n: f32) -> Self {
        Self::new(self.x.powf(n), self.y.powf(n))
    }

    /// Returns `self` with the square root value of each component.
    #[inline]
    #[must_use]
    pub fn sqrt(self) -> Self {
        Self::new(self.x.sqrt(), self.y.sqrt())
    }

    /// Returns `self` with the sine value of each component.
    #[inline]
    #[must_use]
    pub fn sin(self) -> Self {
        Self::new(self.x.sin(), self.y.sin())
    }

    /// Returns `self` with the cosine value of each component.
    #[inline]
    #[must_use]
    pub fn cos(self) -> Self {
        Self::new(self.x.cos(), self.y.cos())
    }

    /// Returns a `(Vec2, Vec2)` with the sine and cosine value of each component of `self`.
    #[inline]
    #[must_use]
    pub fn sin_cos(self) -> (Self, Self) {
        let (sin_x, cos_x): (f32, f32) = self.x.sin_cos();
        let (sin_y, cos_y): (f32, f32) = self.y.sin_cos();

        (Self::new(sin_x, sin_y), Self::new(cos_x, cos_y))
    }

    /// Returns `self` with the reciprocal value of each component.
    #[inline]
    #[must_use]
    pub const fn recip(self) -> Self {
        Self::new(self.x.recip(), self.y.recip())
    }

    /// Returns `self` with the nearest integer to each component.
    /// If a component is half-way between two integers, round away from 0.0.
    #[inline]
    #[must_use]
    pub const fn round(self) -> Self {
        Self::new(self.x.round(), self.y.round())
    }

    /// Returns `self` with the largest integer less than or equal to each component.
    #[inline]
    #[must_use]
    pub const fn floor(self) -> Self {
        Self::new(self.x.floor(), self.y.floor())
    }

    /// Returns `self` with the smallest integer less than or equal to each component.
    #[inline]
    #[must_use]
    pub const fn ceil(self) -> Self {
        Self::new(self.x.ceil(), self.y.ceil())
    }

    /// Returns a `Vec2` linearly interpolated between `self` and `to`, with factor `t`.
    #[inline]
    #[must_use]
    pub const fn lerp(self, to: Self, t: f32) -> Self {
        self.add(to.sub(self).mul_scalar(t))
    }

    /// Returns a `Vec2` linearly interpolated between `self` and `to`, with factor `t`.
    ///
    /// Clamps `t` between `0.0` and `1.0`.
    #[inline]
    #[must_use]
    pub const fn lerp_clamped(self, to: Self, t: f32) -> Self {
        self.lerp(to, t.clamp(0.0, 1.0))
    }

    /// Returns a `Vec2` incrementally moved from `self` to `to`, by at most `max_delta` distance,
    /// without overshooting.
    #[inline]
    #[must_use]
    pub fn move_towards(self, to: Self, max_delta: f32) -> Self {
        let delta: Self = to - self;
        let distance: f32 = delta.length();

        if distance < Self::EPSILON || distance <= max_delta {
            return to;
        }

        self + delta / distance * max_delta
    }

    /// Returns `true` if `self` and `other` approximately represent the same point.
    ///
    /// Uses [`EPSILON`](Self::EPSILON) as the threshold.
    #[inline]
    #[must_use]
    pub const fn approx_eq(self, other: Self) -> bool {
        self.distance_squared(other) < Self::EPSILON_SQ
    }

    /// Returns `true` if all components of `self` are finite.
    #[inline]
    #[must_use]
    pub const fn is_finite(self) -> bool {
        self.x.is_finite() && self.y.is_finite()
    }

    /// Returns `true` if any components of `self` is `NaN`.
    #[inline]
    #[must_use]
    pub const fn is_nan(self) -> bool {
        self.x.is_nan() || self.y.is_nan()
    }
}

impl Add for Vec2 {
    type Output = Self;

    /// Returns the component-wise sum of `self` and `rhs`.
    ///
    /// Equivalent to [`add`](Self::add()).
    #[inline]
    fn add(self, rhs: Self) -> Self::Output {
        self.add(rhs)
    }
}

impl AddAssign for Vec2 {
    /// Sets `self` to the component-wise sum of `self` and `rhs`.
    ///
    /// Equivalent to [`add_assign`](Self::add_assign()).
    #[inline]
    fn add_assign(&mut self, rhs: Self) {
        self.add_assign(rhs);
    }
}

impl Add<f32> for Vec2 {
    type Output = Self;

    /// Returns `self` with `rhs` added to each component.
    ///
    /// Equivalent to [`add_scalar`](Self::add_scalar()).
    #[inline]
    fn add(self, rhs: f32) -> Self::Output {
        self.add_scalar(rhs)
    }
}

impl AddAssign<f32> for Vec2 {
    /// Sets `self` to `self` with `rhs` added to each component.
    ///
    /// Equivalent to [`add_assign_scalar`](Self::add_assign_scalar()).
    #[inline]
    fn add_assign(&mut self, rhs: f32) {
        self.add_assign_scalar(rhs);
    }
}

impl Add<Vec2> for f32 {
    type Output = Vec2;

    /// Returns `rhs` with `self` added to each component.
    ///
    /// Equivalent to [`add_scalar`](Vec2::add_scalar()).
    #[inline]
    fn add(self, rhs: Vec2) -> Self::Output {
        rhs.add_scalar(self)
    }
}

impl Sub for Vec2 {
    type Output = Self;

    /// Returns the component-wise difference of `self` and `rhs`.
    ///
    /// Equivalent to [`sub`](Self::sub()).
    #[inline]
    fn sub(self, rhs: Self) -> Self::Output {
        self.sub(rhs)
    }
}

impl SubAssign for Vec2 {
    /// Sets `self` to the component-wise difference of `self` and `rhs`.
    ///
    /// Equivalent to [`sub_assign`](Self::sub_assign()).
    #[inline]
    fn sub_assign(&mut self, rhs: Self) {
        self.sub_assign(rhs);
    }
}

impl Sub<f32> for Vec2 {
    type Output = Self;

    /// Returns `self` with `rhs` subtracted from each component.
    ///
    /// Equivalent to [`sub_scalar`](Self::sub_scalar()).
    #[inline]
    fn sub(self, rhs: f32) -> Self::Output {
        self.sub_scalar(rhs)
    }
}

impl SubAssign<f32> for Vec2 {
    /// Sets `self` to `self` with `rhs` subtracted from each component.
    ///
    /// Equivalent to [`sub_assign_scalar`](Self::sub_assign_scalar()).
    #[inline]
    fn sub_assign(&mut self, rhs: f32) {
        self.sub_assign_scalar(rhs);
    }
}

impl Mul for Vec2 {
    type Output = Self;

    /// Returns the component-wise product of `self` and `rhs`.
    ///
    /// Equivalent to [`mul`](Self::mul()).
    #[inline]
    fn mul(self, rhs: Self) -> Self::Output {
        self.mul(rhs)
    }
}

impl MulAssign for Vec2 {
    /// Sets `self` to the component-wise product of `self` and `rhs`.
    ///
    /// Equivalent to [`mul_assign`](Self::mul_assign()).
    #[inline]
    fn mul_assign(&mut self, rhs: Self) {
        self.mul_assign(rhs);
    }
}

impl Mul<f32> for Vec2 {
    type Output = Self;

    /// Returns `self` with each component multiplied by `rhs`.
    ///
    /// Equivalent to [`mul_scalar`](Self::mul_scalar()).
    #[inline]
    fn mul(self, rhs: f32) -> Self::Output {
        self.mul_scalar(rhs)
    }
}

impl MulAssign<f32> for Vec2 {
    /// Sets `self` to `self` with each component multiplied by `rhs`.
    ///
    /// Equivalent to [`mul_assign_scalar`](Self::mul_assign_scalar()).
    #[inline]
    fn mul_assign(&mut self, rhs: f32) {
        self.mul_assign_scalar(rhs);
    }
}

impl Mul<Vec2> for f32 {
    type Output = Vec2;

    /// Returns `rhs` with each component multiplied by `self`.
    ///
    /// Equivalent to [`mul_scalar`](Vec2::mul_scalar()).
    #[inline]
    fn mul(self, rhs: Vec2) -> Self::Output {
        rhs.mul_scalar(self)
    }
}

impl Div for Vec2 {
    type Output = Self;

    /// Returns the component-wise quotient of `self` and `rhs`.
    ///
    /// Equivalent to [`div`](Self::div()).
    #[inline]
    fn div(self, rhs: Self) -> Self::Output {
        self.div(rhs)
    }
}

impl DivAssign for Vec2 {
    /// Sets `self` to the component-wise quotient of `self` and `rhs`.
    ///
    /// Equivalent to [`div_assign`](Self::div_assign()).
    #[inline]
    fn div_assign(&mut self, rhs: Self) {
        self.div_assign(rhs);
    }
}

impl Div<f32> for Vec2 {
    type Output = Self;

    /// Returns `self` with each component divided by `rhs`.
    ///
    /// Equivalent to [`div_scalar`](Self::div_scalar()).
    #[inline]
    fn div(self, rhs: f32) -> Self::Output {
        self.div_scalar(rhs)
    }
}

impl DivAssign<f32> for Vec2 {
    /// Sets `self` to `self` with each component divided by `rhs`.
    ///
    /// Equivalent to [`div_assign_scalar`](Self::div_assign_scalar()).
    #[inline]
    fn div_assign(&mut self, rhs: f32) {
        self.div_assign_scalar(rhs);
    }
}

impl Rem for Vec2 {
    type Output = Self;

    /// Returns `self` with each component taken modulo `rhs`.
    ///
    /// Equivalent to [`rem`](Self::rem()).
    #[inline]
    fn rem(self, rhs: Self) -> Self::Output {
        self.rem(rhs)
    }
}

impl RemAssign for Vec2 {
    /// Sets `self` to `self` with each component taken modulo `rhs`.
    ///
    /// Equivalent to [`rem_assign`](Self::rem_assign()).
    #[inline]
    fn rem_assign(&mut self, rhs: Self) {
        self.rem_assign(rhs);
    }
}

impl Rem<f32> for Vec2 {
    type Output = Self;

    /// Returns `self` with each component taken modulo `rhs`.
    ///
    /// Equivalent to [`rem_scalar`](Self::rem_scalar()).
    #[inline]
    fn rem(self, rhs: f32) -> Self::Output {
        self.rem_scalar(rhs)
    }
}

impl RemAssign<f32> for Vec2 {
    /// Sets `self` to `self` with each component taken modulo `rhs`.
    ///
    /// Equivalent to [`rem_assign_scalar`](Self::rem_assign_scalar()).
    #[inline]
    fn rem_assign(&mut self, rhs: f32) {
        self.rem_assign_scalar(rhs);
    }
}

impl Neg for Vec2 {
    type Output = Self;

    /// Returns `self` with negated components.
    ///
    /// Equivalent to [`neg`](Self::neg()).
    #[inline]
    fn neg(self) -> Self::Output {
        self.neg()
    }
}

impl Index<usize> for Vec2 {
    type Output = f32;

    /// Returns a reference to the component at `index`.
    ///
    /// `0` maps to `x`, `1` maps to `y`.
    ///
    /// Equivalent to [`index`](Self::index()).
    ///
    /// # Panics
    /// Panics if `index` is greater than `1`.
    #[inline]
    fn index(&self, index: usize) -> &Self::Output {
        self.index(index)
    }
}

impl IndexMut<usize> for Vec2 {
    /// Returns a mutable reference to the component at `index`.
    ///
    /// `0` maps to `x`, `1` maps to `y`.
    ///
    /// Equivalent to [`index_mut`](Self::index_mut()).
    ///
    /// # Panics
    /// Panics if `index` is greater than `1`.
    #[inline]
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        self.index_mut(index)
    }
}

impl AsRef<[f32; 2]> for Vec2 {
    /// Returns a reference to the components as `[x, y]`.
    ///
    /// Equivalent to [`as_ref`](Self::as_ref()).
    ///
    /// # Safety
    /// Relies on `Vec2` being `#[repr(C)]`
    #[inline]
    fn as_ref(&self) -> &[f32; 2] {
        self.as_ref()
    }
}

impl AsMut<[f32; 2]> for Vec2 {
    /// Returns a reference to the components as `[x, y]`.
    ///
    /// Equivalent to [`as_mut`](Self::as_mut()).
    ///
    /// # Safety
    /// Relies on `Vec2` being `#[repr(C)]`
    #[inline]
    fn as_mut(&mut self) -> &mut [f32; 2] {
        self.as_mut()
    }
}

impl Sum for Vec2 {
    /// Sums an iterator of `Vec2` by component-wise addition, starting from [`ZERO`](Self::ZERO).
    #[inline]
    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
        iter.fold(Self::ZERO, Self::add)
    }
}

impl<'a> Sum<&'a Vec2> for Vec2 {
    /// Sums an iterator of `Vec2` by component-wise addition, starting from [`ZERO`](Self::ZERO).
    #[inline]
    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
        iter.fold(Self::ZERO, |a, &b| a.add(b))
    }
}

impl Product for Vec2 {
    /// Multiplies an iterator of `Vec2` component-wise, starting from [`ONE`](Self::ONE).
    #[inline]
    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
        iter.fold(Self::ONE, Self::mul)
    }
}

impl<'a> Product<&'a Vec2> for Vec2 {
    /// Multiplies an iterator of `Vec2` component-wise, starting from [`ONE`](Self::ONE).
    #[inline]
    fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
        iter.fold(Self::ONE, |a, &b| a.mul(b))
    }
}

impl Display for Vec2 {
    /// Formats `self` as `(x, y)`.
    ///
    /// Respects the precision of `f`.
    #[inline]
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if let Some(p) = f.precision() {
            write!(f, "({:.*}, {:.*})", p, self.x, p, self.y)
        } else {
            write!(f, "({}, {})", self.x, self.y)
        }
    }
}

impl Default for Vec2 {
    /// Default is [`ZERO`](Self::ZERO).
    #[inline]
    fn default() -> Self {
        Self::ZERO
    }
}

impl From<[f32; 2]> for Vec2 {
    /// Creates a `Vec2` from `[x, y]`.
    #[inline]
    fn from(v: [f32; 2]) -> Self {
        Self::from_array(v)
    }
}

impl From<Vec2> for [f32; 2] {
    /// Creates `[x, y]` from a `Vec2`.
    ///
    /// Equivalent to [`to_array`](Vec2::to_array()).
    #[inline]
    fn from(v: Vec2) -> Self {
        v.to_array()
    }
}

impl From<&[f32]> for Vec2 {
    /// Creates a `Vec2` from first 2 values of `v`.
    ///
    /// Equivalent to [`from_slice`](Self::from_slice()).
    ///
    /// # Panics
    /// Panics if `v` is less than 2 elements long.
    #[inline]
    fn from(v: &[f32]) -> Self {
        Self::from_slice(v)
    }
}

impl From<Vec3> for Vec2 {
    /// Creates a `Vec2` from the `x` and `y` components of a `Vec3`, with `z` discarded.
    ///
    /// Equivalent to [`from_vec3`](Self::from_vec3()).
    #[inline]
    fn from(v: Vec3) -> Self {
        Self::from_vec3(v)
    }
}

impl From<Vec4> for Vec2 {
    /// Creates a `Vec2` from the `x` and `y` components of a `Vec4`, with `z` and `w` discarded.
    ///
    /// Equivalent to [`from_vec4`](Self::from_vec4()).
    #[inline]
    fn from(v: Vec4) -> Self {
        Self::from_vec4(v)
    }
}

#[cfg(feature = "serde")]
impl serde::Serialize for Vec2 {
    /// Serializes as `[x, y]`.
    ///
    /// # Format
    /// Encoded as a flat 2-element array. Component order matches [`to_array`](Self::to_array()).
    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        self.to_array().serialize(serializer)
    }
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Vec2 {
    /// Deserializes from `[x, y]`.
    ///
    /// # Format
    /// Decoded as a flat 2-element array. Component order matches [`from_array`](Self::from_array()).
    ///
    /// # Errors
    /// Returns an error if array is not exactly 2 elements.
    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        <[f32; 2]>::deserialize(deserializer).map(Self::from_array)
    }
}

#[cfg(feature = "bytemuck")]
unsafe impl bytemuck::Zeroable for Vec2 {}

#[cfg(feature = "bytemuck")]
unsafe impl bytemuck::Pod for Vec2 {}
