using System;
using OpenTK;

namespace SharpQuake
{
	internal static class mathlib
	{
		public static void AngleVectors(ref Vector3 angles, out Vector3 forward, out Vector3 right, out Vector3 up)
		{
			double num = (double)angles.Y * 0.017453292519943295;
			double num2 = Math.Sin(num);
			double num3 = Math.Cos(num);
			double num4 = (double)angles.X * 0.017453292519943295;
			double num5 = Math.Sin(num4);
			double num6 = Math.Cos(num4);
			double num7 = (double)angles.Z * 0.017453292519943295;
			double num8 = Math.Sin(num7);
			double num9 = Math.Cos(num7);
			forward.X = (float)(num6 * num3);
			forward.Y = (float)(num6 * num2);
			forward.Z = (float)(-(float)num5);
			right.X = (float)(-1.0 * num8 * num5 * num3 + -1.0 * num9 * -(float)num2);
			right.Y = (float)(-1.0 * num8 * num5 * num2 + -1.0 * num9 * num3);
			right.Z = (float)(-1.0 * num8 * num6);
			up.X = (float)(num9 * num5 * num3 + -(float)num8 * -(float)num2);
			up.Y = (float)(num9 * num5 * num2 + -(float)num8 * num3);
			up.Z = (float)(num9 * num6);
		}

		public static float Normalize(ref Vector3 v)
		{
			float length = v.Length;
			if (length != 0f)
			{
				float num = 1f / length;
				v.X *= num;
				v.Y *= num;
				v.Z *= num;
			}
			return length;
		}

		public static float Length(ref v3f v)
		{
			return (float)Math.Sqrt((double)(v.x * v.x + v.y * v.y + v.z * v.z));
		}

		public static float LengthXY(ref v3f v)
		{
			return (float)Math.Sqrt((double)(v.x * v.x + v.y * v.y));
		}

		public static float Normalize(ref v3f v)
		{
			float num = (float)Math.Sqrt((double)(v.x * v.x + v.y * v.y + v.z * v.z));
			if (num != 0f)
			{
				float num2 = 1f / num;
				v.x *= num2;
				v.y *= num2;
				v.z *= num2;
			}
			return num;
		}

		public static void VectorMA(ref v3f a, float scale, ref v3f b, out v3f c)
		{
			c.x = a.x + b.x * scale;
			c.y = a.y + b.y * scale;
			c.z = a.z + b.z * scale;
		}

		public static void VectorScale(ref v3f a, float scale, out v3f b)
		{
			b.x = a.x * scale;
			b.y = a.y * scale;
			b.z = a.z * scale;
		}

		public static void VectorAdd(ref v3f a, ref v3f b, out v3f c)
		{
			c.x = a.x + b.x;
			c.y = a.y + b.y;
			c.z = a.z + b.z;
		}

		public static void VectorSubtract(ref v3f a, ref v3f b, out v3f c)
		{
			c.x = a.x - b.x;
			c.y = a.y - b.y;
			c.z = a.z - b.z;
		}

		public static void Clamp(ref v3f src, ref Vector3 min, ref Vector3 max, out v3f dest)
		{
			dest.x = Math.Max(Math.Min(src.x, max.X), min.X);
			dest.y = Math.Max(Math.Min(src.y, max.Y), min.Y);
			dest.z = Math.Max(Math.Min(src.z, max.Z), min.Z);
		}

		public static float DotProduct(ref v3f a, ref v3f b)
		{
			return a.x * b.x + a.y * b.y + a.z * b.z;
		}

		public static bool CheckNaN(ref v3f v, float defValue)
		{
			bool result = false;
			if (float.IsNaN(v.x))
			{
				result = true;
				v.x = defValue;
			}
			if (float.IsNaN(v.y))
			{
				result = true;
				v.y = defValue;
			}
			if (float.IsNaN(v.z))
			{
				result = true;
				v.z = defValue;
			}
			return result;
		}

		public static float Comp(ref v3f a, int index)
		{
			if (index < 0 || index > 2)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			if (index == 0)
			{
				return a.x;
			}
			if (index != 1)
			{
				return a.z;
			}
			return a.y;
		}

		public static float Comp(ref Vector3 a, int index)
		{
			if (index < 0 || index > 2)
			{
				throw new ArgumentOutOfRangeException("index");
			}
			if (index == 0)
			{
				return a.X;
			}
			if (index != 1)
			{
				return a.Z;
			}
			return a.Y;
		}

		public static float AngleMod(double a)
		{
			return (float)(0.0054931640625 * (double)((int)(a * 182.04444444444445) & 65535));
		}

		public static float DotProduct(ref Vector3 a, ref Vector4 b)
		{
			return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
		}

		public static int BoxOnPlaneSide(ref v3f emins, ref v3f emaxs, mplane_t p)
		{
			float num;
			float num2;
			switch (p.type)
			{
			case 0:
				num = emins.x;
				num2 = emaxs.x;
				break;
			case 1:
				num = emins.y;
				num2 = emaxs.y;
				break;
			case 2:
				num = emins.z;
				num2 = emaxs.z;
				break;
			default:
			{
				Vector3 vector;
				mathlib.Copy(ref emins, out vector);
				Vector3 vector2;
				mathlib.Copy(ref emaxs, out vector2);
				return mathlib._BoxOnPlaneSide(ref vector, ref vector2, p);
			}
			}
			if (p.dist <= num)
			{
				return 1;
			}
			if (p.dist < num2)
			{
				return 3;
			}
			return 2;
		}

		public static int BoxOnPlaneSide(ref Vector3 emins, ref Vector3 emaxs, mplane_t p)
		{
			float num;
			float num2;
			switch (p.type)
			{
			case 0:
				num = emins.X;
				num2 = emaxs.X;
				break;
			case 1:
				num = emins.Y;
				num2 = emaxs.Y;
				break;
			case 2:
				num = emins.Z;
				num2 = emaxs.Z;
				break;
			default:
				return mathlib._BoxOnPlaneSide(ref emins, ref emaxs, p);
			}
			if (p.dist <= num)
			{
				return 1;
			}
			if (p.dist < num2)
			{
				return 3;
			}
			return 2;
		}

		public static void SetComp(ref Vector3 dest, int index, float value)
		{
			if (index == 0)
			{
				dest.X = value;
				return;
			}
			if (index == 1)
			{
				dest.Y = value;
				return;
			}
			if (index == 2)
			{
				dest.Z = value;
				return;
			}
			throw new ArgumentException("Index must be in range 0-2!");
		}

		public static void CorrectAngles180(ref Vector3 a)
		{
			if (a.X > 180f)
			{
				a.X -= 360f;
			}
			else if (a.X < -180f)
			{
				a.X += 360f;
			}
			if (a.Y > 180f)
			{
				a.Y -= 360f;
			}
			else if (a.Y < -180f)
			{
				a.Y += 360f;
			}
			if (a.Z > 180f)
			{
				a.Z -= 360f;
				return;
			}
			if (a.Z < -180f)
			{
				a.Z += 360f;
			}
		}

		public static void RotatePointAroundVector(out Vector3 dst, ref Vector3 dir, ref Vector3 point, float degrees)
		{
			Matrix3 matrix = Matrix3.CreateFromAxisAngle(dir, (float)((double)degrees * 3.1415926535897931 / 180.0));
			Vector3.Transform(ref point, ref matrix, out dst);
		}

		public static void Copy(ref v3f src, out Vector3 dest)
		{
			dest.X = src.x;
			dest.Y = src.y;
			dest.Z = src.z;
		}

		public static void Copy(ref Vector3 src, out v3f dest)
		{
			dest.x = src.X;
			dest.y = src.Y;
			dest.z = src.Z;
		}

		private static int _BoxOnPlaneSide(ref Vector3 emins, ref Vector3 emaxs, mplane_t p)
		{
			float num;
			float num2;
			switch (p.signbits)
			{
			case 0:
				num = p.normal.X * emaxs.X + p.normal.Y * emaxs.Y + p.normal.Z * emaxs.Z;
				num2 = p.normal.X * emins.X + p.normal.Y * emins.Y + p.normal.Z * emins.Z;
				break;
			case 1:
				num = p.normal.X * emins.X + p.normal.Y * emaxs.Y + p.normal.Z * emaxs.Z;
				num2 = p.normal.X * emaxs.X + p.normal.Y * emins.Y + p.normal.Z * emins.Z;
				break;
			case 2:
				num = p.normal.X * emaxs.X + p.normal.Y * emins.Y + p.normal.Z * emaxs.Z;
				num2 = p.normal.X * emins.X + p.normal.Y * emaxs.Y + p.normal.Z * emins.Z;
				break;
			case 3:
				num = p.normal.X * emins.X + p.normal.Y * emins.Y + p.normal.Z * emaxs.Z;
				num2 = p.normal.X * emaxs.X + p.normal.Y * emaxs.Y + p.normal.Z * emins.Z;
				break;
			case 4:
				num = p.normal.X * emaxs.X + p.normal.Y * emaxs.Y + p.normal.Z * emins.Z;
				num2 = p.normal.X * emins.X + p.normal.Y * emins.Y + p.normal.Z * emaxs.Z;
				break;
			case 5:
				num = p.normal.X * emins.X + p.normal.Y * emaxs.Y + p.normal.Z * emins.Z;
				num2 = p.normal.X * emaxs.X + p.normal.Y * emins.Y + p.normal.Z * emaxs.Z;
				break;
			case 6:
				num = p.normal.X * emaxs.X + p.normal.Y * emins.Y + p.normal.Z * emins.Z;
				num2 = p.normal.X * emins.X + p.normal.Y * emaxs.Y + p.normal.Z * emaxs.Z;
				break;
			case 7:
				num = p.normal.X * emins.X + p.normal.Y * emins.Y + p.normal.Z * emins.Z;
				num2 = p.normal.X * emaxs.X + p.normal.Y * emaxs.Y + p.normal.Z * emaxs.Z;
				break;
			default:
				num2 = (num = 0f);
				sys.Error("BoxOnPlaneSide:  Bad signbits", Array.Empty<object>());
				break;
			}
			int num3 = 0;
			if (num >= p.dist)
			{
				num3 = 1;
			}
			if (num2 < p.dist)
			{
				num3 |= 2;
			}
			return num3;
		}
	}
}
