
#include "cgMath.h"

namespace gravity
{

	cgColor::cgColor()
	{
		r = 0.0f;
		g = 0.0f;
		b = 0.0f;
		a = 1.0f;
	}

	cgColor::cgColor( const float * f )
	{
		r = (*f);
		g = (*f) + 1;
		b = (*f) + 2;
		a = (*f) + 3;
	}

	cgColor::cgColor( float r, float g, float b )
	{
		this->r = r;
		this->g = g;
		this->b = b;
		this->a = 1.0f;
	}

	cgColor::cgColor( float r, float g, float b, float a )
	{
		this->r = r;
		this->g = g;
		this->b = b;
		this->a = a;
	}

	cgColor::operator float* ()
	{
		return (float*) this;
	}

	cgColor::operator const float* () const
	{
		return (const float*) this;
	}

	cgColor& cgColor::operator += ( const cgColor& c )
	{
		(*this) = (*this) + c;

		return (*this);
	}

	cgColor& cgColor::operator -= ( const cgColor& c )
	{
		(*this) = (*this) - c;

		return (*this);
	}

	cgColor& cgColor::operator *= ( float s )
	{
		(*this) = (*this) * s;

		return (*this);
	}

	cgColor& cgColor::operator /= ( float s )
	{
		(*this) = (*this) / s;

		return (*this);
	}

	cgColor cgColor::operator + () const
	{
		return cgColor(r, g, b, a);
	}

	cgColor cgColor::operator - () const
	{
		return cgColor(-r, -g, -b, -a);
	}

	cgColor cgColor::operator + ( const cgColor& c ) const
	{
		return cgColor(r + c.r, g + c.g, b + c.b, a + c.a);
	}

	cgColor cgColor::operator - ( const cgColor& c ) const
	{
		return cgColor(r - c.r, g - c.g, b - c.b, a - c.a);
	}

	cgColor cgColor::operator * ( float s ) const
	{
		return cgColor(r * s, g * s, b * s, a * s);
	}

	cgColor cgColor::operator / ( float s ) const
	{
		return (s == 0.0f) ? cgColor() : cgColor(r / s, g / s, b / s, a / s);
	}

	cgColor operator * ( float s, const cgColor& c )
	{
		return c * s;
	}

	bool cgColor::operator == ( const cgColor& c ) const
	{
		return (r == c.r && g == c.g && b == c.b && a == c.a) ? true : false;
	}

	bool cgColor::operator != ( const cgColor& c ) const
	{
		return (r != c.r && g != c.g && b != c.b && a != c.a) ? true : false;
	}

	void cgColor::add(const cgColor *c)
	{
		r += c->r;
		g += c->g;
		b += c->b;
		a += c->a;
	}

	void cgColor::adjustContrast(float a)
	{
		r = 0.5f + a * (r - 0.5f);
		g = 0.5f + a * (g - 0.5f);
		b = 0.5f + a * (b - 0.5f);
	}

	void cgColor::adjustSaturation(float a)
	{
		// Approximate values for each component's contribution to luminance.
		// Based upon the NTSC standard described in ITU-R Recommendation BT.709.
		float grey = r * 0.2125f + g * 0.7154f + b * 0.0721f;

		r = grey + a * (r - grey);
		g = grey + a * (g - grey);
		b = grey + a * (b - grey);
	}

	void cgColor::clamp()
	{
		r = (r > 0.0f) ? ((r < 1.0f) ? r : 1.0f) : 0.0f;
		g = (g > 0.0f) ? ((g < 1.0f) ? g : 1.0f) : 0.0f;
		b = (b > 0.0f) ? ((b < 1.0f) ? b : 1.0f) : 0.0f;
		a = (a > 0.0f) ? ((a < 1.0f) ? a : 1.0f) : 0.0f;
	}

	void cgColor::lerp(const cgColor *c, float s)
	{
		r = r + s * (c->r - r);
		g = g + s * (c->g - g);
		b = b + s * (c->b - b);
		a = a + s * (c->a - a);
	}

	void cgColor::modulate(const cgColor *c)
	{
		r *= c->r;
		g *= c->g;
		b *= c->b;
		a *= c->a;
	}

	void cgColor::negative()
	{
		r = 1.0f - r;
		g = 1.0f - g;
		b = 1.0f - b;
		a = 1.0f - a;
	}

	void cgColor::scale(float s)
	{
		r *= s;
		g *= s;
		b *= s;
		a *= s;
	}

	void cgColor::subtract(const cgColor *c)
	{
		r = (r - c->r) > 0.0f ? r - c->r : 0.0f;
		g = (g - c->g) > 0.0f ? g - c->g : 0.0f;
		b = (b - c->b) > 0.0f ? b - c->b : 0.0f;
		a = (a - c->a) > 0.0f ? a - c->a : 0.0f;
	}

}