using System;
using System.Collections;
using System.Text;

namespace Example
{
	[CRepr]
	public struct Vector2
	{
		public float mX;
		public float mY;

		public static Vector2 sZero = Vector2(0f, 0f);
		public static Vector2 sOne = Vector2(1f, 1f);
		public static Vector2 sUnitX = Vector2(1f, 0f);
		public static Vector2 sUnitY = Vector2(0f, 1f);
		public static Vector2 sUp = Vector2(0f, 1f);
		public static Vector2 sDown = Vector2(0f, -1f);
		public static Vector2 sRight = Vector2(1f, 0f);
		public static Vector2 sLeft = Vector2(-1f, 0f);

		public float Length
		{
			get
			{
				return (float)Math.Sqrt(mX * mX + mY * mY);
			}
		}

		public float LengthSquared
		{
			get
			{
				return mX * mX + mY * mY;
			}
		}

		public float Angle
		{
			get
			{
				return Math.Atan2(mY, mX);
			}
		}

		public this(float x, float y)
		{
			mX = x;
			mY = y;
		}

		public static void DistanceSquared(Vector2 value1, Vector2 value2, out float result)
		{
			result = (value1.mX - value2.mX) * (value1.mX - value2.mX) +
				(value1.mY - value2.mY) * (value1.mY - value2.mY);
		}

		public static float Distance(Vector2 vector1, Vector2 vector2)
		{
			float result;
			DistanceSquared(vector1, vector2, out result);
			return (float)Math.Sqrt(result);
		}

		public static Vector2 Add(Vector2 vec1, Vector2 vec2)
		{
			return Vector2(vec1.mX + vec2.mX, vec1.mY + vec2.mY);
		}

		public static Vector2 Subtract(Vector2 vec1, Vector2 vec2)
		{
			return Vector2(vec1.mX - vec2.mX, vec1.mY - vec2.mY);
		}

		public static float Dot(Vector2 vec1, Vector2 vec2)
		{
			return vec1.mX * vec2.mX + vec1.mY * vec2.mY;
		}

		public static Vector2 FromAngle(float angle, float length = 1.0f)
		{
			return Vector2((float)Math.Cos(angle) * length, (float)Math.Sin(angle) * length);
		}

		public static Vector2 operator+(Vector2 vec1, Vector2 vec2)
		{
			return Vector2(vec1.mX + vec2.mX, vec1.mY + vec2.mY);
		}

		public static Vector2 operator-(Vector2 vec1, Vector2 vec2)
		{
			return Vector2(vec1.mX - vec2.mX, vec1.mY - vec2.mY);
		}

		public static Vector2 operator*(Vector2 vec1, float factor)
		{
			return Vector2(vec1.mX * factor, vec1.mY * factor);
		}

		public static Vector2 operator/(Vector2 vec1, float factor)
		{
			return Vector2(vec1.mX / factor, vec1.mY / factor);
		}
	}
}
