using System;
namespace Engine.Core;
/// 
/// Represents a three-dimensional integer vector.
/// 
/// X position of the .
/// Y position of the .
/// Z position of the .
/// 
/// Initializes a new instance of the  struct with the specified positions.
/// 
[System.Diagnostics.DebuggerDisplay("{ToString(),nq}")]
public readonly struct Vector3DInt(int x, int y, int z) : IEquatable
{
    /// 
    /// The X coordinate of the .
    /// 
    public readonly int X = x;
    /// 
    /// The Y coordinate of the .
    /// 
    public readonly int Y = y;
    /// 
    /// The Z coordinate of the .
    /// 
    public readonly int Z = z;
    /// 
    /// The magnitude (length) of the .
    /// 
    public float Magnitude => Length(this);
    /// 
    /// The squared magnitude (length) of the .
    /// 
    public float MagnitudeSquared => LengthSquared(this);
    /// 
    /// Represents the unit  pointing upwards.
    /// 
    public readonly static Vector3DInt Up = new(0, 1, 0);
    /// 
    /// Represents the unit  pointing downwards.
    /// 
    public readonly static Vector3DInt Down = new(0, -1, 0);
    /// 
    /// Represents the unit  pointing leftwards.
    /// 
    public readonly static Vector3DInt Left = new(-1, 0, 0);
    /// 
    /// Represents the unit  pointing rightwards.
    /// 
    public readonly static Vector3DInt Right = new(1, 0, 0);
    /// 
    /// Represents the unit  pointing forwards.
    /// 
    public readonly static Vector3DInt Forward = new(0, 0, 1);
    /// 
    /// Represents the unit  pointing backwards.
    public readonly static Vector3DInt Backward = new(0, 0, -1);
    /// 
    /// Represents the zero .
    /// 
    public readonly static Vector3DInt Zero = new(0, 0, 0);
    /// 
    /// Represents the  with both components equal to 1.
    /// 
    public readonly static Vector3DInt One = new(1, 1, 1);
    public static Vector3DInt operator -(Vector3DInt vector) => new(0 - vector.X, 0 - vector.Y, 0 - vector.Z);
    public static Vector3DInt operator +(Vector3DInt left, Vector3DInt right) => new(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
    public static Vector3DInt operator -(Vector3DInt left, Vector3DInt right) => new(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
    public static bool operator ==(Vector3DInt left, Vector3DInt right) => left.X == right.X && left.Y == right.Y && left.Z == right.Z;
    public static bool operator !=(Vector3DInt left, Vector3DInt right) => left.X != right.X || left.Y != right.Y || left.Z != right.Z;
    public static implicit operator Vector3DInt(Vector3D vector) => new(vector.X.RoundToInt(), vector.Y.RoundToInt(), vector.Z.RoundToInt());
    public static implicit operator Vector3DInt(Vector2DInt vector) => new(vector.X, vector.Y, 0);
    /// 
    /// Calculates the length of the .
    /// 
    /// The .
    /// The length of the .
    public static float Length(Vector3DInt vector) => Math.Sqrt(LengthSquared(vector));
    /// 
    /// Calculates the squared length of the .
    /// 
    /// The .
    /// The squared length of the .
    public static float LengthSquared(Vector3DInt vector) => vector.X * vector.X + vector.Y * vector.Y + vector.Z * vector.Z;
    /// 
    /// Calculates the distance between two s.
    /// 
    /// The start .
    /// The end .
    /// The distance between the two s.
    public static float Distance(Vector3DInt from, Vector3DInt to) => Length(FromTo(from, to));
    /// 
    /// Inverts the direction of the .
    /// 
    /// The .
    /// The inverted .
    public static Vector3DInt Invert(Vector3DInt vector) => -vector;
    /// 
    /// Adds two s.
    /// 
    /// The first .
    /// The second .
    /// The sum of the two s.
    public static Vector3DInt Add(Vector3DInt left, Vector3DInt right) => left + right;
    /// 
    /// Subtracts one  from another.
    /// 
    /// The  to subtract from.
    /// The  to subtract.
    /// The result of subtracting the second  from the first.
    public static Vector3DInt Subtract(Vector3DInt left, Vector3DInt right) => left - right;
    /// 
    /// Calculates the absolute value of each component of the vector.
    /// 
    /// The .
    /// The  with each component's absolute value.
    public static Vector3DInt Abs(Vector3DInt vector) => new(Math.Abs(vector.X), Math.Abs(vector.Y), Math.Abs(vector.Z));
    /// 
    /// Calculates the  from one point to another.
    /// 
    /// The starting point.
    /// The ending point.
    /// The  from the starting point to the ending point.
    public static Vector3DInt FromTo(Vector3DInt from, Vector3DInt to) => to - from;
    /// 
    /// Scales a  by another  component-wise.
    /// 
    /// The  to scale.
    /// The  containing the scaling factors for each component.
    /// The scaled .
    public static Vector3DInt Scale(Vector3DInt vector, Vector3DInt scale) => new(vector.X * scale.X, vector.Y * scale.Y, vector.Z * scale.Z);
    /// 
    /// Returns the component-wise minimum of two s.
    /// 
    /// The first .
    /// The second .
    /// The  containing the minimum components from both input s.
    public static Vector3DInt Min(Vector3DInt left, Vector3DInt right) => new((left.X < right.X) ? left.X : right.X, (left.Y < right.Y) ? left.Y : right.Y, (left.Z < right.Z) ? left.Z : right.Z);
    /// 
    /// Returns the component-wise maximum of two s.
    /// 
    /// The first .
    /// The second .
    /// The  containing the maximum components from both input s.
    public static Vector3DInt Max(Vector3DInt left, Vector3DInt right) => new((left.X > right.X) ? left.X : right.X, (left.Y > right.Y) ? left.Y : right.Y, (left.Z > right.Z) ? left.Z : right.Z);
    /// 
    /// Clamps each component of a  between the corresponding component of two other s.
    /// 
    /// The  to clamp.
    /// The  representing the minimum values for each component.
    /// The  representing the maximum values for each component.
    /// A  with each component clamped between the corresponding components of the min and max s.
    public static Vector3DInt Clamp(Vector3DInt vector, Vector3DInt min, Vector3DInt max) => new(Math.Clamp(vector.X, min.X, max.X), Math.Clamp(vector.Y, min.Y, max.Y), Math.Clamp(vector.Z, min.Z, max.Z));
    /// 
    /// Calculates the cross product of two s.
    /// 
    /// The first .
    /// The second .
    /// The cross product of the two s.
    public static Vector3DInt Cross(Vector3DInt left, Vector3DInt right) => new(left.Y * right.Z - left.Z * right.Y, left.Z * right.X - left.X * right.Z, left.X * right.Y - left.Y * right.X);
    /// 
    /// Calculates the angle between two s.
    /// 
    /// The first .
    /// The second .
    /// The angle between the two s in radians.
    public static float Angle(Vector3DInt left, Vector3DInt right) => Math.Acos(Dot(left, right) / (Length(left) * Length(right)));
    /// 
    /// Calculates the dot product of two s.
    /// 
    /// The first .
    /// The second .
    /// The dot product of the two s.
    public static int Dot(Vector3DInt left, Vector3DInt right) => left.X * right.X + left.Y * right.Y + left.Z * right.Z;
    /// 
    /// Determines whether the specified object is equal to the current .
    /// 
    /// The object to compare with the current .
    ///  if the specified object is equal to the current ; otherwise, .
    public override bool Equals(object? obj) => obj is Vector3DInt vector3D && this == vector3D;
    public bool Equals(Vector3DInt other) => this == other;
    /// 
    /// Generates a hash code for the .
    /// 
    /// A hash code for the .
    public override int GetHashCode() => System.HashCode.Combine(X, Y, Z);
    /// 
    /// Converts the  to its string representation.
    /// 
    /// A string representation of the .
    public override string ToString() => $"{nameof(Vector3DInt)}({X}, {Y}, {Z})";
}
/// 
/// Provides extension methods for  type.
/// 
public static class Vector3DIntExtensions
{
    /// 
    public static float Length(this Vector3DInt vector) => Vector3DInt.Length(vector);
    /// 
    public static float LengthSquared(this Vector3DInt vector) => Vector3DInt.LengthSquared(vector);
    /// 
    public static float Distance(this Vector3DInt from, Vector3DInt to) => Vector3DInt.Distance(from, to);
    /// 
    public static Vector3DInt Invert(this Vector3DInt vector) => Vector3DInt.Invert(vector);
    /// 
    public static Vector3DInt Add(this Vector3DInt vector, Vector3DInt vectorToAdd) => Vector3DInt.Add(vector, vectorToAdd);
    /// 
    public static Vector3DInt Subtract(this Vector3DInt vector, Vector3DInt vectorToSubtract) => Vector3DInt.Subtract(vector, vectorToSubtract);
    /// 
    public static Vector3DInt Abs(this Vector3DInt vector) => Vector3DInt.Abs(vector);
    /// 
    public static Vector3DInt FromTo(this Vector3DInt from, Vector3DInt to) => Vector3DInt.FromTo(from, to);
    /// 
    public static Vector3DInt Scale(this Vector3DInt vector, Vector3DInt scale) => Vector3DInt.Scale(vector, scale);
    /// 
    public static Vector3DInt Min(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Min(left, right);
    /// 
    public static Vector3DInt Max(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Max(left, right);
    /// 
    public static Vector3DInt Clamp(this Vector3DInt vector, Vector3DInt min, Vector3DInt max) => Vector3DInt.Clamp(vector, min, max);
    /// 
    public static Vector3DInt Cross(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Cross(left, right);
    /// 
    public static float AngleBetween(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Angle(left, right);
    /// 
    public static int Dot(this Vector3DInt left, Vector3DInt right) => Vector3DInt.Dot(left, right);
}