////////////////////////////////////////////////////////////////////////////////
// Color.cpp
// Copyright Bjoern Ganster
// Developed since 2000
////////////////////////////////////////////////////////////////////////////////

#include "Color.h"

// Constructor
Color::Color(ColorBase red, ColorBase green, ColorBase blue, ColorBase transparency)
: VirtualClass ("Color", ColorID),
  r(red),
  g(green),
  b(blue),
  a(transparency)
{
}

// Destructor
Color::~Color()
{
}

// Produce a random color
Color Color::random(ColorBase transparency)
{
	return Color(frand<ColorBase>(), frand<ColorBase>(), frand<ColorBase>(), transparency);
}

// Apply
void Color::glColor () const
{
	glColor4d (r, g, b, a);
}

// Binary addition
Color Color::operator+ (const Color& c) const 
{
	return Color (r+c.r, g+c.g, b+c.b, (a + c.a) / 2);
}

// Binary multiplication
Color Color::operator* (const Color& c) const 
{
	return Color (r*c.r, g*c.g, b*c.b, a*c.a);
}

// Multiplication with scalar
Color Color::operator* (ColorBase f) const 
{
	return Color (r*f, g*f, b*f);
}

// Comparison with Color
bool Color::operator == (const Color& c) const
{
	return fabs (r-c.r) <= 0.5 / 255.0 
	&& fabs (g-c.g) <= 0.5 / 255.0
	&& fabs (b-c.b) <= 0.5 / 255.0; 
}

bool Color::operator!= (const Color& c) const
{
	return fabs (r-c.r) > 0.5 / 255.0 
	|| fabs (g-c.g) > 0.5 / 255.0 
	|| fabs (b-c.b) > 0.5 / 255.0;
}

Color Color::red ()
{
	return Color (1.0, 0.0, 0.0);
}

Color Color::green ()
{
	return Color (0.0, 1.0, 0.0);
}

Color Color::blue ()
{
	return Color (0.0, 0.0, 1.0);
}

Color Color::white ()
{
	return Color (1.0, 1.0, 1.0);
}

Color Color::black ()
{
	return Color (0.0, 0.0, 0.0);
}

////////////////////////////////////////////////////////////////////////////////
// Parse hex. color entries such as ff ff ff (white), 80 80 80 (grey) or ff 00 00 (red)

Color parseColor (const BGCPString& line)
{
    Color result;
    if (!line.empty()) {
		auto words = line.split(" ", false);
         BGCPString& num = words[0];
         result.r = (ColorBase) (num.toInt(16)/255.0);

        num = words[1];
        result.g = (ColorBase) (num.toInt(16)/255.0);

        num = words[2];
        result.b = (ColorBase) (num.toInt(16)/255.0);

        if (words.size() > 3) {
	        num = words[3];
            result.a = (ColorBase) (num.toInt(16)/255.0);
		} else
            result.a = 1.0;
    }

    return result;
}

Color interpolateColor(ColorBase val, ColorBase minVal, 
    ColorBase maxVal, const Color& minColor, const Color& maxColor)
{
    if (val < minVal)
        return minColor;
    else if (val > maxVal)
        return maxColor;
    else {
        ColorBase v2 = (val-minVal)/(maxVal-minVal);
        ColorBase v1 = 1.0f - v2;
        return Color (v1 * minColor.r + v2 * maxColor.r,
            v1 * minColor.g + v2 * maxColor.g,
            v1 * minColor.b + v2 * maxColor.b);
    }
}
