/*
   math/color.cc
   This file is part of the Osirion project and is distributed under
   the terms of the GNU General Public License version 2
*/

// project headers
#include "math/color.h"

namespace math
{

Color::Color() :
	r(rgba_data[0]),
	g(rgba_data[1]),
	b(rgba_data[2]),
	a(rgba_data[3])
{
	assign(1.0f, 1.0f);
}

Color::Color(float red, float green, float blue, float alpha) :
	r(rgba_data[0]),
	g(rgba_data[1]),
	b(rgba_data[2]),
	a(rgba_data[3])
{
	assign(red, green, blue, alpha);
}

Color::Color(const float grey, const float alpha) : 
	r(rgba_data[0]),
	g(rgba_data[1]),
	b(rgba_data[2]),
	a(rgba_data[3])
{
	assign(grey, alpha);
}

Color::Color(Color const &other) : 
	r(rgba_data[0]),
	g(rgba_data[1]),
	b(rgba_data[2]),
	a(rgba_data[3])
{
	assign(other);
}


void Color::assign(float red, float green, float blue, float alpha)
{
	rgba_data[0] = red;
	rgba_data[1] = green;
	rgba_data[2] = blue;
	rgba_data[3] = alpha;
}

void Color::assign(Color const & other)
{
	memcpy(rgba_data, other.rgba_data, sizeof(rgba_data));
}

void Color::assign(float grey, float alpha)
{
	rgba_data[0] = rgba_data[1] = rgba_data[2] = grey;
	rgba_data[3] = alpha;
}

const Color & Color::operator=(Color const & other)
{
	assign(other);
	return *this;
}

void Color::clamp()
{
	for (int i =0; i < 4; i++)
		if (rgba_data[i] < 0)
			rgba_data[i] = 0;

	float tmp = rgba_data[0];
	if (rgba_data[1] > tmp)
		tmp = rgba_data[1];
	if (rgba_data[2] > tmp)
		tmp = rgba_data[2];

	if (tmp > 1) {
		for (int i =0; i < 3; i++)
			rgba_data[i] /= tmp;
	}

	if (rgba_data[3] > 1)
		rgba_data[3] = 1;
}

float Color::red() const
{
	return rgba_data[0];
}

float Color::green() const
{
	return rgba_data[1];
}

float Color::blue() const
{
	return rgba_data[2];
}

float Color::alpha() const
{
	return rgba_data[3];
}

Color Color::operator*(float scalar) const
{
	return Color(red()*scalar, green()*scalar, blue()*scalar, alpha());
}

Color const operator*(float scalar, Color const & color)
{
	return color * scalar;
}
std::ostream &operator<<(std::ostream &os, Color const & color)
{
	os <<  color.red() << " " << color.green() << " " << color.blue(); // << " " << c.alpha();
	return os;
}

std::istream &operator>>(std::istream & is, Color & color)
{
	is >> color.r;
	is >> color.g;
	is >> color.b;
	//is >> color.a;
	color.a = 1.0;
	return (is);
}

} // namespace math