#ifndef _COMMON_RGBCOLOR_HPP_
#define _COMMON_RGBCOLOR_HPP_
#ifndef _COMMON_WINDOWS_HPP_
#include <common/windows.hpp>
#endif

class RGBColor
{
public:
	RGBColor(void);
	RGBColor(const RGBColor &someRGBColor);
	RGBColor(COLORREF someColor);
	RGBColor(unsigned char red,unsigned char green,unsigned char blue);
	void red(unsigned char red);
  unsigned char red(void)const;
	void green(unsigned char green);
  unsigned char green(void)const;
	void blue(unsigned char blue);
	unsigned char blue(void)const;
	WORD operator==(const RGBColor &someRGBColor)const;
	RGBColor &operator=(const RGBColor &someRGBColor);
  RGBColor &operator=(COLORREF someColor);
	RGBColor &operator+=(unsigned char colorByte);
	RGBColor &operator-=(unsigned char colorByte);
  WORD operator<(const RGBColor &someRGBColor)const;
	LONG operator-(const RGBColor &someRGBColor)const;
	operator COLORREF(void)const;
	COLORREF getCOLORREF(void)const;
private:
	enum {MaxColorByte=255};
  LONG magnitude(void)const;
	unsigned char mRed;
	unsigned char mGreen;
	unsigned char mBlue;
};

inline
RGBColor::RGBColor(void)
: mRed(0), mGreen(0), mBlue(0)
{
}

inline
RGBColor::RGBColor(const RGBColor &someRGBColor)
{
	*this=someRGBColor;
}

inline
RGBColor::RGBColor(COLORREF someColor)
{
  *this=someColor;
}

inline
RGBColor::RGBColor(unsigned char red,unsigned char green,unsigned char blue)
: mRed(red), mGreen(green), mBlue(blue)
{
}

inline
void RGBColor::red(unsigned char red)
{
  mRed=red;
}

inline
unsigned char RGBColor::red(void)const
{
	return mRed;
}

inline
void RGBColor::green(unsigned char green)
{
	mGreen=green;
}

inline
unsigned char RGBColor::green(void)const
{
	return mGreen;
}

inline
void RGBColor::blue(unsigned char blue)
{
	mBlue=blue;
}

inline
unsigned char RGBColor::blue(void)const
{
	return mBlue;
}

inline
RGBColor &RGBColor::operator=(const RGBColor &someRGBColor)
{
	red(someRGBColor.red());
	green(someRGBColor.green());
	blue(someRGBColor.blue());
  return *this;
}

inline
RGBColor &RGBColor::operator=(COLORREF someColor)
{
	red((BYTE)(someColor&0xFF));
	green((BYTE)((someColor>>8)&0xFF));
	blue((BYTE)((someColor>>16)&0xFF));
	return *this;
}

inline
WORD RGBColor::operator==(const RGBColor &someRGBColor)const
{
	return (red()==someRGBColor.red()&&
					green()==someRGBColor.green()&&
					blue()==someRGBColor.blue());
}

inline
LONG RGBColor::operator-(const RGBColor &someRGBColor)const
{
	LONG redDiff((LONG)mRed-(LONG)someRGBColor.mRed);
	LONG greenDiff((LONG)mGreen-(LONG)someRGBColor.mGreen);
  LONG blueDiff((LONG)mBlue-(LONG)someRGBColor.mBlue);
  return ((redDiff*redDiff)+(greenDiff*greenDiff)+(blueDiff*blueDiff));
}

inline
RGBColor &RGBColor::operator+=(unsigned char colorByte)
{
  short tmpColor;

  tmpColor=(short)mRed+(short)colorByte;
  mRed=(tmpColor<=MaxColorByte?tmpColor:MaxColorByte);
	tmpColor=(short)mGreen+(short)colorByte;
  mGreen=(tmpColor<=MaxColorByte?tmpColor:MaxColorByte);
  tmpColor=(short)mBlue+(short)colorByte;
  mBlue=(tmpColor<=MaxColorByte?tmpColor:MaxColorByte);
  return *this;
}

inline
RGBColor &RGBColor::operator-=(unsigned char colorByte)
{
	mRed-=(colorByte>=mRed?mRed:colorByte);
	mGreen-=(colorByte>=mGreen?mGreen:colorByte);
	mBlue-=(colorByte>=mBlue?mBlue:colorByte);
	return *this;
}

inline
RGBColor::operator COLORREF(void)const
{
  return getCOLORREF();
}

inline
COLORREF RGBColor::getCOLORREF(void)const
{
	COLORREF thisColor;

	thisColor=(COLORREF)(mBlue)<<16;
	thisColor+=(COLORREF)(mGreen)<<8;
	thisColor+=mRed;
	return thisColor;
}

inline
WORD RGBColor::operator<(const RGBColor &someRGBColor)const
{
	return magnitude()<someRGBColor.magnitude();
}

inline
LONG RGBColor::magnitude(void)const
{
	return ((LONG)mRed*(LONG)mRed)+((LONG)mGreen*(LONG)mGreen)+((LONG)mBlue*(LONG)mBlue);
}
#endif
