#ifndef __gxframework_vector2_h__
	#define __gxframework_vector2_h__

#include "shared.h"
#include "gxmath.h"

//TODO: isNormalized

namespace Gx
{
	class Vector2
	{
	public:
		Vector2() { }
		Vector2(float a) : x(a), y(a) { }
		Vector2(float a[]) : x(a[0]), y(a[1]) { }
		Vector2(float nx, float ny) : x(nx), y(ny) { }
		Vector2(const Vector2& v) { x = v.x; y = v.y; }
		Vector2& operator=(const Vector2& v) { x = v.x; y = v.y; return *this; }

		static Vector2 zero() { return Vector2(0, 0); }

		float& operator[](unsigned int index) { ASSERT(index >= 0 && index <= 1); return (&x)[index]; }
		const float& operator[](unsigned int index) const { ASSERT(index >= 0 && index <= 1); return (&x)[index]; }

		bool operator==(const Vector2& v) const { return x == v.x && y == v.y; }
		bool operator!=(const Vector2& v) const { return x != v.x || y != v.y; }

		bool isZero() const { return x == float(0) && y == float(0); }
		bool isFinite() const { return Gx::isFinite(x) && Gx::isFinite(y); }

		float magnitudeSquared() const { return x * x + y * y;}
		float magnitude() const { return ::sqrt( this->magnitudeSquared() ); }
		float length() const { return magnitude(); }

		float dot(const Vector2& v) { return x * v.x + y * v.y; }

		Vector2 operator-() const { return Vector2(-x, -y); }

		Vector2 operator+(const Vector2& v) const { return Vector2(x + v.x, y + v.y); }
		Vector2 operator-(const Vector2& v) const { return Vector2(x - v.x, y - v.y); }
		//Vector2 operator*(const Vector2& v) const { return Vector2(x * v.x, y * v.y); } // mnożenie wektorów

		Vector2 operator*(float scalar) const { return Vector2(x * scalar, y * scalar); }
		Vector2 operator/(float scalar) const { scalar = float(1) / scalar; return Vector2(x * scalar, y * scalar); }

		Vector2& operator+=(const Vector2& v) { x += v.x; y += v.y; return *this; }
		Vector2& operator-=(const Vector2& v) { x -= v.x; y -= v.y; return *this; }

		Vector2& operator*=(float scalar) { x *= scalar; y *= scalar; return *this; }
		Vector2& operator/=(float scalar) { scalar = float(1) / scalar; x *= scalar; y *= scalar; return *this; }

		Vector2 getNormalized() const { const float m = this->magnitude(); return m > 0 ? (*this / m) : Vector2(0,0); }

		float normalize() { const float m = magnitude(); if (m > 0) { *this /= m; } return m; }

		Vector2 multiply(const Vector2& v) const { return Vector2(x * v.x, y * v.y); }

		Vector2 minimum(const Vector2& v) const { return Vector2(std::min(x, v.x), std::min(y, v.y)); }
		Vector2 maximum(const Vector2& v) const { return Vector2(std::max(x, v.x), std::max(y, v.y)); }
		
		float minElement() const { return std::min(x, y); }
		float maxElement() const { return std::max(x, y); }

		float x, y;
	};

	static Vector2 operator*(float scalar, const Vector2& v)
	{
		return Vector2(scalar * v.x, scalar * v.y);
	}
}

#endif // ~__gxframework_vector2_h__
