
#ifndef SPECTRE_MATH_VECTOR2_H
#define SPECTRE_MATH_VECTOR2_H

#include <string>
#include <iostream>

template <typename T>
struct Vector2
{
	union {
		struct { 
			T x, y;
		};
		T v[2];
	};

	inline Vector2();

	inline Vector2(T s);

	inline Vector2(T x, T y);

	template <typename U>
	inline Vector2(const Vector2<U>& vec);

	// -----------------
	// Named operations.
	// -----------------

	inline float length() const;

	inline Vector2<T>& normalize();

	// Dot product
	inline T dot(const Vector2<T>& vec) const;

	inline Vector2<T>& reflect(const Vector2<T>& n);

	std::string toString() const;
};

// ------------
//  Compare
// ------------

template<typename T>
inline bool operator==(const Vector2<T>& a, const Vector2<T>& b);

template<typename T>
inline bool operator!=(const Vector2<T>& a, const Vector2<T>& b);

template<typename T>
inline bool operator<(const Vector2<T>& a, const Vector2<T>& b);

template<typename T>
inline bool operator<=(const Vector2<T>& a, const Vector2<T>& b);

template<typename T>
inline bool operator>(const Vector2<T>& a, const Vector2<T>& b);

template<typename T>
inline bool operator>=(const Vector2<T>& a, const Vector2<T>& b);

// ------------------
//  Unary arithmetic
// ------------------

template <typename T>
inline Vector2<T> operator+(const Vector2<T>& v);

template <typename T>
inline Vector2<T> operator-(const Vector2<T>& v);

// ------------
//  Arithmetic
// ------------

template<typename T>
inline Vector2<T> operator+(const Vector2<T>& a, const Vector2<T>& b);

template<typename T>
inline Vector2<T> operator-(const Vector2<T>& a, const Vector2<T>& b);

template<typename T>
inline Vector2<T> operator/(const Vector2<T>& a, const Vector2<T>& b);

template<typename T>
inline Vector2<T> operator*(const Vector2<T>& a, const Vector2<T>& b);

template<typename T>
inline Vector2<T>& operator+=(Vector2<T>& a, const Vector2<T>& b);

template<typename T>
inline Vector2<T>& operator-=(Vector2<T>& a, const Vector2<T>& b);

template<typename T>
inline Vector2<T>& operator/=(Vector2<T>& a, const Vector2<T>& b);

template<typename T>
inline Vector2<T>& operator*=(Vector2<T>& a, const Vector2<T>& b);

// -------------------
//  Scalar Arithmetic
// -------------------

template <typename T>
inline Vector2<T> operator+(const Vector2<T>& v, T s);

template <typename T>
inline Vector2<T> operator+(T s, const Vector2<T>& v);

template <typename T>
inline Vector2<T> operator-(const Vector2<T>& v,T s);

template <typename T>
inline Vector2<T> operator-(T s, const Vector2<T>& v);

template <typename T>
inline Vector2<T> operator/(const Vector2<T>& v, T s);

template <typename T>
inline Vector2<T> operator/(T s, const Vector2<T>& v);

template <typename T>
inline Vector2<T> operator*(const Vector2<T>& v, T s);

template <typename T>
inline Vector2<T> operator*(T s, const Vector2<T>& v);

template <typename T>
inline Vector2<T>& operator+=(Vector2<T>& v, T s);

template <typename T>
inline Vector2<T>& operator-=(Vector2<T>& v,T s);

template <typename T>
inline Vector2<T>& operator/=(Vector2<T>& v, T s);

template <typename T>
inline Vector2<T>& operator*=(Vector2<T>& v, T s);


// ----------------
//  Scalar compare
// ----------------

template <typename T>
inline bool operator<(const Vector2<T>& v, T s);

template <typename T>
inline bool operator<(T s, const Vector2<T>& v);

template <typename T>
inline bool operator<=(const Vector2<T>& v, T s);

template <typename T>
inline bool operator<=(T s, const Vector2<T>& v);

template <typename T>
inline bool operator>(const Vector2<T>& v, T s);

template <typename T>
inline bool operator>(T s, const Vector2<T>& v);

template <typename T>
inline bool operator>=(const Vector2<T>& v, T s);

template <typename T>
inline bool operator>=(T s, const Vector2<T>& v);

// -------------------
//  Stream operations
// -------------------

template <typename T>
inline std::ostream& operator<<(std::ostream &s, const Vector2<T>& v);

// -----------------------------
//  Common specialization types
// -----------------------------

typedef Vector2<float>		Vector2f;
typedef Vector2<int>		Vector2i;
typedef Vector2<unsigned>	Vector2u;
typedef Vector2<unsigned char>	Vector2b;

typedef Vector2<float>		vec2f;
typedef Vector2<int>		vec2i;
typedef Vector2<unsigned>	vec2u;
typedef Vector2<unsigned char>	vec2b;

#include "Vector2.inl"

#endif /* SPECTRE_MATH_VECTOR2_H */
