//-----------------------------------------------------------------------------------------------
// Rgba.hpp
//
#pragma once
#ifndef include_Rgba
#define include_Rgba

//-----------------------------------------------------------------------------------------------
#include "Engine/Core/EngineBase.hpp"


/////////////////////////////////////////////////////////////////////////////////////////////////
class Rgba
{
public:
	unsigned char	r; // 0-255 red byte
	unsigned char	g; // 0-255 green byte
	unsigned char	b; // 0-255 blue byte
	unsigned char	a; // 0-255 alpha (opacity) byte

public:
	static const Rgba BLACK;
	static const Rgba WHITE;
	static const Rgba RED;
	static const Rgba GREEN;
	static const Rgba BLUE;
	static const Rgba YELLOW;
	static const Rgba MAGENTA;
	static const Rgba CYAN;
	static const Rgba SILVER;
	static const Rgba GREY;
	static const Rgba DARKGREY;
	static const Rgba DEEPGREY;
	static const Rgba DARKRED;
	static const Rgba DARKGREEN;
	static const Rgba DARKBLUE;
	static const Rgba PURPLE;
	static const Rgba DARKYELLOW;
	static const Rgba DARKCYAN;
	static const Rgba ORANGE;

	static const Rgba ORGANIC_RED;
	static const Rgba ORGANIC_ORANGE;
	static const Rgba ORGANIC_YELLOW;
	static const Rgba ORGANIC_GREEN;
	static const Rgba ORGANIC_BLUE;
	static const Rgba ORGANIC_PURPLE;
	static const Rgba ORGANIC_GREY;
	static const Rgba ORGANIC_BROWN;

	static const Rgba ORGANIC_DIM_RED;
	static const Rgba ORGANIC_DIM_YELLOW;
	static const Rgba ORGANIC_DIM_GREEN;
	static const Rgba ORGANIC_DIM_BLUE;
	static const Rgba ORGANIC_DIM_PURPLE;

	static const Rgba GAINSBORO;
	static const Rgba JET;
	static const Rgba CHARCOAL;
	static const Rgba PINK;
	static const Rgba ASH;

public:
	~Rgba() {}
	Rgba() {}
	Rgba( unsigned char redByte, unsigned char greenByte, unsigned char blueByte, unsigned char alphaByte=255 );
	Rgba( const char* asText );

	void SetFromText( const char* asText );
	void ScaleRGB( float rgbScale );
	void ScaleAlpha( float alphaScale );
//	void SetRGBFloats( float red, float green, float blue );
	void SetRGBAFloats( float red, float green, float blue, float alpha );

	const unsigned char* GetAsByteArray() const { return &r; }
	unsigned char* GetAsByteArray() { return &r; }
	void GetRGBAFloats( float& out_r, float& out_g, float& out_b, float& out_a ) const;
	void GetRGBFloats( float& out_r, float& out_g, float& out_b ) const;
	const Rgba GetFaded( float alphaScale ) const;

	bool operator == ( const Rgba& rhsCompare ) const;

public:
	static float ConvertColorByteToFloat( unsigned char colorByte );
	static unsigned char ConvertFloatToColorByte( float colorChannelZeroToOne );
	friend const Rgba Interpolate( const Rgba& startColor, const Rgba& endColor, float fractionTowardEnd );

private:
	static const int MAX_RGBA_COMMAS;

private:
	void SpliceIntoSubstrings( const char* originalText, char* splicedText, char** substringStarts );
};


/////////////////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------------------------
inline Rgba::Rgba( unsigned char redByte, unsigned char greenByte, unsigned char blueByte, unsigned char alphaByte )
	: r( redByte )
	, g( greenByte )
	, b( blueByte )
	, a( alphaByte )
{
}


//-----------------------------------------------------------------------------------------------
inline void Rgba::GetRGBAFloats( float& out_r, float& out_g, float& out_b, float& out_a ) const
{
	out_r = ConvertColorByteToFloat( r );
	out_g = ConvertColorByteToFloat( g );
	out_b = ConvertColorByteToFloat( b );
	out_a = ConvertColorByteToFloat( a );
}


//-----------------------------------------------------------------------------------------------
inline void Rgba::GetRGBFloats( float& out_r, float& out_g, float& out_b ) const
{
	out_r = ConvertColorByteToFloat( r );
	out_g = ConvertColorByteToFloat( g );
	out_b = ConvertColorByteToFloat( b );
}


//-----------------------------------------------------------------------------------------------
inline const Rgba Rgba::GetFaded( float alphaScale ) const
{
	Rgba faded( *this );
	faded.ScaleAlpha( alphaScale );
	return faded;
}


//-----------------------------------------------------------------------------------------------
// inline void Rgba::SetRGBFloats( float redZeroToOne, float greenZeroToOne, float blueZeroToOne )
// {
// 	r = ConvertFloatToColorByte( redZeroToOne );
// 	g = ConvertFloatToColorByte( greenZeroToOne );
// 	b = ConvertFloatToColorByte( blueZeroToOne );
// //	a = 0xFF; // Leave alpha unchanged from prior?
// }


//-----------------------------------------------------------------------------------------------
inline void Rgba::SetRGBAFloats( float redZeroToOne, float greenZeroToOne, float blueZeroToOne, float alphaZeroToOne )
{
	r = ConvertFloatToColorByte( redZeroToOne );
	g = ConvertFloatToColorByte( greenZeroToOne );
	b = ConvertFloatToColorByte( blueZeroToOne );
	a = ConvertFloatToColorByte( alphaZeroToOne );
}


//-----------------------------------------------------------------------------------------------
inline void Rgba::ScaleRGB( float rgbScale )
{
	int byteScale = (int)( rgbScale * 256.f );
	r =	(unsigned char)( ( byteScale * (int)r ) >> 8 );
	g =	(unsigned char)( ( byteScale * (int)g ) >> 8 );
	b =	(unsigned char)( ( byteScale * (int)b ) >> 8 );
}


//-----------------------------------------------------------------------------------------------
inline void Rgba::ScaleAlpha( float alphaScale )
{
	int byteScale = (int)( alphaScale * 256.f );
	a =	(unsigned char)( ( byteScale * (int)a ) >> 8 );
}


//-----------------------------------------------------------------------------------------------
inline bool Rgba::operator == ( const Rgba& rhsCompare ) const
{
	return(	r == rhsCompare.r &&
			g == rhsCompare.g &&
			b == rhsCompare.b &&
			a == rhsCompare.a );
}


//-----------------------------------------------------------------------------------------------
inline STATIC float Rgba::ConvertColorByteToFloat( unsigned char colorByte )
{
	float colorByteAsFloat = static_cast< float >( colorByte );
	return colorByteAsFloat * (1.f / 255.f);
}


//-----------------------------------------------------------------------------------------------
inline STATIC unsigned char Rgba::ConvertFloatToColorByte( float colorChannelZeroToOne )
{
	float colorByteAsFloat = (colorChannelZeroToOne * 255.f) + 0.5f;
	return static_cast< unsigned char >( colorByteAsFloat );
}


//-----------------------------------------------------------------------------------------------
inline const Rgba Interpolate( const Rgba& startColor, const Rgba& endColor, float fractionTowardEnd )
{
	Rgba lerpedColor;
	float startFraction = (1.f - fractionTowardEnd);
	lerpedColor.r = (unsigned char)( (startFraction * (float) startColor.r) + (fractionTowardEnd * (float) endColor.r) );
	lerpedColor.g = (unsigned char)( (startFraction * (float) startColor.g) + (fractionTowardEnd * (float) endColor.g) );
	lerpedColor.b = (unsigned char)( (startFraction * (float) startColor.b) + (fractionTowardEnd * (float) endColor.b) );
	lerpedColor.a = (unsigned char)( (startFraction * (float) startColor.a) + (fractionTowardEnd * (float) endColor.a) );
	return lerpedColor;
}




#endif // include_Rgba
