#include "Salamander.h"
#include "Vec2.h"

namespace Salamander
{

Vec2::Vec2(double x, double y) : Vec(),
	x_(x), 
	y_(y)
{
	
}

Vec2::~Vec2()
{

}

// Equals
bool Vec2::operator== (const Vec2& v)
{
	return v.x_ == x_ && 
		   v.y_ == y_;
}

// Does not equal
bool Vec2::operator!= (const Vec2& v)
{
	return v.x_ != x_ || 
		   v.y_ != y_;
}

// Negate
Vec2 Vec2::operator-()
{
	return Vec2(-x_, -y_);
}

// Perpendicular
Vec2 Vec2::operator~()
{
	return Vec2(y_, -x_);
}

// Scalar multiply
Vec2 Vec2::operator* (double s)
{
	return Vec2(x_ * s, y_ * s);
}

// Scalar divide
Vec2 Vec2::operator/ (double s)
{
	return Vec2(x_ / s, y_ / s);
}

// Scalar perpendicular
Vec2 Vec2::operator^ (double s)
{
	return Vec2(y_ * s, x_ * -s);
}

// Component add
Vec2 Vec2::operator+ (const Vec2& v)
{
	return Vec2(x_ + v.x_, y_ + v.y_);
}

// Component subtract
Vec2 Vec2::operator- (const Vec2& v)
{
	return Vec2(x_ - v.x_, y_ - v.y_);
}

// Dot product
double Vec2::operator* (const Vec2& v)
{
	return (x_ * v.x_) + (y_ * v.y_);
}

// Perp-dot product
Vec2 Vec2::operator| (const Vec2& v)
{
	return Vec2(x_ * v.y_, y_ * v.x_);
}

// Component divide
Vec2 Vec2::operator/ (const Vec2& v)
{
	return Vec2(x_ / v.x_, y_ / v.y_);
}

// Cross product
double Vec2::operator^ (const Vec2& v)
{
	return x_ * v.y_ - y_ * v.x_;
}

// Scalar multiply increment
Vec2& Vec2::operator*= (double s)
{
	x_ *= s;
	y_ *= s;
	dirty_ = true;
	return *this;
}

// Scalar divide increment
Vec2& Vec2::operator/= (double s)
{
	x_ /= s;
	y_ /= s;
	dirty_ = true;
	return *this;
}

// Vector increment
Vec2& Vec2::operator+= (const Vec2& v)
{
	x_ += v.x_;
	y_ += v.y_;
	dirty_ = true;
	return *this;
}

// Vector decrement
Vec2& Vec2::operator-= (const Vec2& v)
{
	x_ -= v.x_;
	y_ -= v.y_;
	dirty_ = true;
	return *this;
}

// Properties
double Vec2::length()
{
	if(dirty_)
	{
		lengthSquared();
		length_ = sqrt(lengthSquared_);
		dirty_ = false;
	}
	return length_;
}

double Vec2::lengthSquared()
{
	if(dirty_) lengthSquared_ = x_ * x_ + 
								y_ * y_;
	return lengthSquared_;
}

// Other operations
Vec2& Vec2::normalise()
{
	if(dirty_) length();
	if(length_ != 0.0f)
	{
		x_ /= length_;
		y_ /= length_;
	}
	return *this;
}

Vec2 Vec2::normal()
{
	if(dirty_) length();
	if(length_ != 0.0f)
	{
		return Vec2(x_ / length_, y_ / length_);
	}
	else
	{
		return Vec2();
	}
}

}