#ifndef _COMMON_PUREPALETTE_HPP_
#define _COMMON_PUREPALETTE_HPP_
#include <string.h>
#ifndef _COMMON_WINDOWS_HPP_
#include <common/windows.hpp>
#endif
#ifndef _COMMON_PUREBITMAP_HPP_
#include <common/purebmp.hpp>
#endif
#ifndef _COMMON_PUREDEVICE_HPP_
#include <common/purehdc.hpp>
#endif
#ifndef _COMMON_RGBCOLOR_HPP_
#include <common/rgbcolor.hpp>
#endif
#ifndef _COMMON_ARRAY_HPP_
#include <common/array.hpp>
#endif
#ifndef _COMMON_PALETTEENTRY_HPP_
#include <common/palentry.hpp>
#endif
#ifndef _COMMON_EXCEPTION_HPP_
#include <common/except.hpp>
#endif
#ifndef _COMMON_ARRAY_HPP_
#include <common/array.hpp>
#endif

class BitmapInfo;

class PurePalette
{
public:
	enum {MaxColors=256};
	enum InitPal{InitSys,InitNone};
	typedef int PaletteIndex;
  PurePalette(InitPal initPal=InitNone);
	PurePalette(HPALETTE hPalette);
	PurePalette(const String &strPathFileName);
	PurePalette(const PurePalette &somePurePalette);
  PurePalette(const BitmapInfo &someBitmapInfo);
	virtual ~PurePalette();
	PurePalette &operator=(const PurePalette &somePurePalette);
	PurePalette &operator=(const BitmapInfo &someBitmapInfo);
	PurePalette &operator=(HPALETTE hPalette);
	PurePalette &operator=(const String &strPathFileName);
	PurePalette &operator=(const Array<PaletteEntry> &paletteData);
	PaletteEntry &operator[](PaletteIndex paletteIndex);
	WORD operator==(const PurePalette &somePurePalette)const;
	WORD identityPalette(void);
  WORD systemPalette(bool useStandardColors=false);
	WORD isIdentityPalette(void)const;
	void cyclePalette(void);
	PaletteIndex paletteIndex(const RGBColor &someRGBColor)const;
  void getPaletteColors(Array<RGBColor> &someRGBColors)const;
  void setPaletteColors(Array<RGBColor> &someRGBColors,PaletteEntry::PaletteFlags paletteFlag=PaletteEntry::NullFlag);
	WORD setPaletteColor(short paletteIndex,RGBColor &someRGBColor,PaletteEntry::PaletteFlags paletteFlag=PaletteEntry::NullFlag);
	WORD getPaletteColor(short paletteIndex,RGBColor &someRGBColor)const;
	void clearPalette(void);
	void usePalette(const PureDevice &somePureDevice,short usage);
	WORD paletteEntry(PaletteIndex paletteIndex,RGBColor &someRGBColor)const;
	RGBColor paletteEntry(PaletteIndex paletteIndex)const;
	DWORD paletteEntries(void)const;
	void paletteEntries(DWORD palEntries);
	WORD isInUse(void)const;
	BOOL readPalette(const String &strPathFileName);
	BOOL writePalette(const String &strPathFileName);
	HPALETTE getPalette(void)const;
private:
  enum {SystemStaticColors=20};
	WORD createPalette(void);
	void setPaletteColors(void)const;
	void destroyPalette(void);

	HPALETTE mhPalette;
	HPALETTE mhOldPalette;
	Array<PaletteEntry> mPaletteData;
	WORD mIsInUse;
};

inline
PurePalette::PurePalette(InitPal initPal)
: mhPalette(0), mhOldPalette(0), mIsInUse(FALSE)
{
  mPaletteData.size(MaxColors);
  if(InitSys==initPal)systemPalette();
	else createPalette();
	return;
}

inline
PurePalette::~PurePalette()
{
  destroyPalette();
	return;
}

inline
DWORD PurePalette::paletteEntries(void)const
{
  return mPaletteData.size();
}

inline
void PurePalette::paletteEntries(DWORD palEntries)
{
  mPaletteData.size(palEntries);
	createPalette();
}

inline
void PurePalette::setPaletteColors(void)const
{
  ::SetPaletteEntries(mhPalette,0,paletteEntries(),(PALETTEENTRY FAR*)&((PurePalette&)*this).mPaletteData[0]);
}

inline
WORD PurePalette::isInUse(void)const
{
	return mIsInUse;
}

inline
PurePalette::PaletteIndex PurePalette::paletteIndex(const RGBColor &someRGBColor)const
{
	return ::GetNearestPaletteIndex(mhPalette,(COLORREF)someRGBColor);
}

inline
PaletteEntry &PurePalette::operator[](PaletteIndex paletteIndex)
{
  if(paletteIndex>=paletteEntries())throw(BoundaryError());
  return mPaletteData[paletteIndex];
}

inline
HPALETTE PurePalette::getPalette(void)const
{
  return mhPalette;
}
#endif

