//	Darkstar Engine  (c) UnderWorld Interactive Studio (all coding by Svarog    2007)
//
//      Данный файл является частью Darkstar Engine. Любое использование кода файла
//      без согласия компании, является нарушением закона об авторском праве (в слу-
//      чае если не оговорено обратное).
//
//      Имя файла: vect.hpp
//      Краткое описание: классы Vect2, Vect3, Vect4
//

#ifndef DSE_MATH_VECT_HPP
#define DSE_MATH_VECT_HPP

#include <Darkstar/common.hpp>

namespace math
{
	class Vect3;
	class Vect4;

	class Vect2
	{
	public:
		union
		{
			struct
			{
				float x, y;
			};
			struct  
			{
				float mas[2];
			};
		};

		Vect2();
		Vect2(const Vect2& v);
		Vect2(const float x, const float y);
		Vect2(const float* xy);
		explicit Vect2(const Vect3& v);
		explicit Vect2(const Vect4& v);
		~Vect2();

		Vect2& operator=(const Vect2& v);

		const float operator[](const unsigned int i) const;
		float& operator[](const unsigned int i);

		Vect2 operator+(const Vect2& v) const;
		const Vect2& operator+=(const Vect2& v);
		Vect2 operator-(const Vect2& v) const;
		const Vect2& operator-=(const Vect2& v);

		Vect2 operator*(const float f) const;
		const Vect2& operator*=(const float f);
		Vect2 operator/(const float f) const;
		const Vect2& operator/=(const float f);

		Vect2 operator-() const;

		bool operator==(const Vect2& v) const;
		bool operator!=(const Vect2& v) const;

		float length() const;
		float sqLength() const;
		const Vect2& normalize();
		Vect2 getNormalize() const;
	};

	class Vect3
	{
	public:
		union
		{
			struct  
			{
				float x, y, z;
			};
			struct
			{
				float mas[3];
			};
		};

		Vect3();
		Vect3(const Vect3& v);
		Vect3(const float x, const float y, const float z);
		Vect3(const float* xyz);
		Vect3(const float val);
		explicit Vect3(const Vect2& v);
		explicit Vect3(const Vect4& v);
		~Vect3();

		Vect3& operator=(const Vect3& v);

		const float operator[](const unsigned int i) const;
		float& operator[](const unsigned int i);

		Vect3 operator+(const Vect3& v) const;
		const Vect3& operator+=(const Vect3& v);
		Vect3 operator-(const Vect3& v) const;
		const Vect3& operator-=(const Vect3& v);

		Vect3 operator*(const float f) const;
		const Vect3& operator*=(const float f);
		Vect3 operator/(const float f) const;
		const Vect3& operator/=(const float f);

		Vect3 operator-() const;

		bool operator==(const Vect3& v) const;
		bool operator!=(const Vect3& v) const;

		float length() const;
		float sqLength() const;
		const Vect3& normalize();
		Vect3 getNormalize() const;
	};

	class Vect4
	{
	public:
		union
		{
			struct
			{
				float x, y, z, w;
			};
			struct
			{
				float mas[4];
			};
		};

		Vect4();
		Vect4(const Vect4& v);
		Vect4(const float x, const float y, const float z, const float w);
		Vect4(const float* xyzw);
		Vect4(const float val);
		explicit Vect4(const Vect2& v);
		explicit Vect4(const Vect3& v);
		~Vect4();

		Vect4& operator=(const Vect4& v);

		const float operator[](const unsigned int i) const;
		float& operator[](const unsigned int i);

		Vect4 operator+(const Vect4& v) const;
		const Vect4& operator+=(const Vect4& v);
		Vect4 operator-(const Vect4& v) const;
		const Vect4& operator-=(const Vect4& v);

		Vect4 operator*(const float f) const;
		const Vect4& operator*=(const float f);
		Vect4 operator/(const float f) const;
		const Vect4& operator/=(const float f);

		Vect4 operator-() const;

		bool operator==(const Vect4& v) const;
		bool operator!=(const Vect4& v) const;

		float length() const;
		float sqLength() const;
		const Vect4& normalize();
		Vect4 getNormalize() const;
	};
	
	float dot(const Vect2& v1, const Vect2& v2);
	float dot(const Vect3& v1, const Vect3& v2);
	float dot(const Vect4& v1, const Vect4& v2);

	Vect3 cross(const Vect3& v1, const Vect3& v2);

	float distance(const Vect2& v1, const Vect2& v2);
	float distance(const Vect3& v1, const Vect3& v2);
	float distance(const Vect4& v1, const Vect4& v2);
	
	float sqDistance(const Vect2& v1, const Vect2& v2);
	float sqDistance(const Vect3& v1, const Vect3& v2);
	float sqDistance(const Vect4& v1, const Vect4& v2);

	std::ostream& operator<<(std::ostream& os, const Vect2& v);
	std::ostream& operator<<(std::ostream& os, const Vect3& v);
	std::ostream& operator<<(std::ostream& os, const Vect4& v);

	std::istream& operator>>(std::istream& is, Vect2& v);
	std::istream& operator>>(std::istream& is, Vect3& v);
	std::istream& operator>>(std::istream& is, Vect4& v);

	const Vect2 vect2_zero = Vect2(0, 0);
	const Vect2 vect2_sing = Vect2(1, 1);
	const Vect2 vect2_sing_x = Vect2(1, 0);
	const Vect2 vect2_sing_y = Vect2(0, 1);

	const Vect3 vect3_zero = Vect3(0, 0, 0);
	const Vect3 vect3_sing = Vect3(1, 1, 1);
	const Vect3 vect3_sing_x = Vect3(1, 0, 0);
	const Vect3 vect3_sing_y = Vect3(0, 1, 0);
	const Vect3 vect3_sing_z = Vect3(0, 0, 1);

	const Vect4 vect4_zero = Vect4(0, 0, 0, 0);
	const Vect4 vect4_sing = Vect4(1, 1, 1, 1);
	const Vect4 vect4_sing_x = Vect4(1, 0, 0, 0);
	const Vect4 vect4_sing_y = Vect4(0, 1, 0, 0);
	const Vect4 vect4_sing_z = Vect4(0, 0, 1, 0);
	const Vect4 vect4_sing_w = Vect4(0, 0, 0, 1);
};

#include <Darkstar/Math/vect.inl>

#endif