#include "Vector.h"
#include <math.h>
#include <assert.h>

namespace cbk
{
	float& Vector::operator[](const int id)
	{
		switch (id)
		{
		case 0:
			return X;
		case 1:
			return Y;
		case 2:
			return Z;
		default:
			assert(false);
			return X;
		}
	}

	const float Vector::magnitude(void) const
	{
		return sqrt((X * X) + (Y * Y) + (Z * Z));
	}

	const float Vector::dot(const Vector& other) const
	{
		return (X * other.X) + (Y * other.Y) + (Z * other.Z);
	}

	const Vector Vector::cross(const Vector& other) const
	{
		return Vector((Y * other.Z) - (Z * other.Y), (X * other.Z) - (Z * other.X), (X * other.Y) - (Y * other.X));
	}

	const float Vector::distance(const Vector& other) const
	{
		const float Dx = X - other.X;
		const float Dy = Y - other.Y;
		const float Dz = Z - other.Z;
		return sqrt((Dx * Dx) + (Dy * Dy) + (Dz * Dz));
	}

	Vector& Vector::normalize(void)
	{
		const float& mag = magnitude();
		X /= mag;
		Y /= mag;
		Z /= mag;

		return *this;
	}

	Vector::Vector(float X, float Y, float Z)
	{
		this->X = X;
		this->Y = Y;
		this->Z = Z;
	}

	Vector::Vector(const D3DXVECTOR3& vector)
	{
		X = vector.x;
		Y = vector.y;
		Z = vector.z;
	}

	Vector::operator D3DXVECTOR3(void) const
	{
		return D3DXVECTOR3(X, Y, Z);
	}

	Vector Vector::operator-(void) const
	{
		return Vector(-X, -Y, -Z);
	}

	bool Vector::operator==(const Vector& other) const
	{
		return ((X == other.X) && (Y == other.Y) && (Z == other.Z));
	}

	bool Vector::operator!=(const Vector& other) const
	{
		return ((X != other.X) || (Y != other.Y) || (Z != other.Z));
	}

	Vector Vector::operator+(const Vector& other) const
	{
		return (Vector(X + other.X, Y + other.Y, Z + other.Z));
	}

	Vector Vector::operator-(const Vector& other) const
	{
		return (Vector(X - other.X, Y - other.Y, Z- other.Z));
	}

	Vector Vector::operator*(const Vector& other) const
	{
		return (Vector(X * other.X, Y * other.Y, Z * other.Z));
	}
	Vector Vector::operator*(const float& other) const
	{
		return (Vector(X * other, Y * other, Z * other));
	}

	Vector Vector::operator/(const Vector& other) const
	{
		return (Vector(X / other.X, Y / other.Y, Z / other.Z));
	}
	Vector Vector::operator/(const float& other) const
	{
		return (Vector(X / other, Y / other, Z / other));
	}

	Vector& Vector::operator+=(const Vector& other)
	{
		X += other.X;
		Y += other.Y;
		Z += other.Z;
		return *this;
	}

	Vector& Vector::operator-=(const Vector& other)
	{
		X -= other.X;
		Y -= other.Y;
		Z -= other.Z;
		return *this;
	}

	Vector& Vector::operator*=(const Vector& other)
	{
		X *= other.X;
		Y *= other.Y;
		Z *= other.Z;
		return *this;
	}
	Vector& Vector::operator*=(const float& other)
	{
		X *= other;
		Y *= other;
		Z *= other;
		return *this;
	}

	Vector& Vector::operator/=(const Vector& other)
	{
		X /= other.X;
		Y /= other.Y;
		Z /= other.Z;
		return *this;
	}

	Vector& Vector::operator/=(const float& other)
	{
		X /= other;
		Y /= other;
		Z /= other;
		return *this;
	}
}
