// ------------------------------------------------------------------------
/*
	author: Jaap Suter
   
	Copyright (C) Electronic Arts Canada Inc. 2002.  All rights reserved.	
*/
// ------------------------------------------------------------------------

/*! \file */

#ifndef REVEAL_COLOR_H
#define REVEAL_COLOR_H

#include "reveal/stdint.h"

namespace Reveal {

// -------------------------------------------------------------------------------
/*!
	\brief Simple color class, with support to convert from RGB to and from HSV
*/
// -------------------------------------------------------------------------------
class Color
{
public:
	
	//! Constructor, initializes to non-translucent black;
	Color() : mA( 1.0f ), mR( 0.0f ), mG( 0.0f ), mB( 0.0f ) {}

	//! Constructor, initializes to the given values;
	Color( float a, float r, float g, float b ) : mA( a ), mR( r ), mG( g ), mB( b ) {}

	//! Constructor, initializes from the given 32 bit ARGB value;
	Color( Reveal::uint32_t c ) 
		: mA( static_cast< float >( (c & 0xFF000000) >> 24 ) / 255.0f ),
		  mR( static_cast< float >( (c & 0x00FF0000) >> 16 ) / 255.0f ),
		  mG( static_cast< float >( (c & 0x0000FF00) >>  8 ) / 255.0f ),
		  mB( static_cast< float >( (c & 0x000000FF)       ) / 255.0f ) {}

	/*! 
		\brief Const Indexing operator, 
		\param i Index of the component, 0 = alpha, 1 = red, 2 = green, 3 = blue, any other index is asserted;
	*/
	float operator [] ( size_t i ) const ;

	/*! 
		\brief Non-const indexing operator, 
		\param i Index of the component, 0 = alpha, 1 = red, 2 = green, 3 = blue, any other index is asserted;
		\return Reference to the component;
	*/
	float& operator [] ( size_t i );

	//! Returns a non const reference to the alpha component;
	float& A() { return mA; }
	
	//! Returns a non const reference to the red component;
	float& R() { return mR; }

	//! Returns a non const reference to the green component;
	float& G() { return mG; }
	
	//! Returns a non const reference to the blue component;
	float& B() { return mB; }

	//! Returns the alpha component;
	float A() const { return mA; }

	//! Returns the red component;
	float R() const { return mR; }
	
	//! Returns the green component;
	float G() const { return mG; }
	
	//! Returns the blue component;
	float B() const { return mB; }

	//! Sets the alpha component;
	void A( float a ) { mA = a; }

	//! Sets the red component;
	void R( float r ) { mR = r; }
	
	//! Sets the green component;
	void G( float g ) { mG = g; }
	
	//! Sets the blue component;
	void B( float b ) { mB = b; }

	//! Returns the alpha component, in an unsigned char in the range 0...255;
	unsigned char ByteA() const { return static_cast< unsigned char >( mA * 255.0f ); }	

	//! Returns the red component, in an unsigned char in the range 0...255;
	unsigned char ByteR() const { return static_cast< unsigned char >( mR * 255.0f ); }	
	
	//! Returns the green component, in an unsigned char in the range 0...255;
	unsigned char ByteG() const { return static_cast< unsigned char >( mG * 255.0f ); }	
	
	//! Returns the blue component, in an unsigned char in the range 0...255;
	unsigned char ByteB() const { return static_cast< unsigned char >( mB * 255.0f ); }	

	//! Returns a 32 bit packed ARGB value;
	//! \warning, this will fail on Nintendo GameCube because of endianness issues;
	Reveal::uint32_t Get32BitARGB() const;

	/*!
		\brief Does a conversion from HSV to RGB;
		\param h, s, v Hue, Saturation, Value
	*/
	void SetFromHSV( float h, float s, float v );

	/*!
		\brief Does a conversion from RGB to HSV;
		\return h, s, v Hue, Saturation, Value
	*/
	void ToHSV( float& h, float& s, float& v ) const;

private:

	float mA;		
	float mR;
	float mG;
	float mB;	
};
 
// -------------------------------------------------------------------------------
namespace Util 
{
	size_t ToString( const Color& c, char* buffer, size_t size );
} // Namespace Util;

} // Namespace Reveal;

#endif

