#ifndef _COMMON_PUREBITMAP_HPP_
#define _COMMON_PUREBITMAP_HPP_
#ifndef _COMMON_ASSERT_HPP_
#include <common/assert.hpp>
#endif
#ifndef _COMMON_WINDOWS_HPP_
#include <common/windows.hpp>
#endif
#ifndef _COMMON_PUREDEVICE_HPP_
#include <common/purehdc.hpp>
#endif
#ifndef _COMMON_STRING_HPP_
#include <common/string.hpp>
#endif
#ifndef _COMMON_GLOBALDATA_HPP_
#include <common/gdata.hpp>
#endif
#ifndef _COMMON_BITMAPINFO_HPP_
#include <common/bminfo.hpp>
#endif

class PureBitmap
{
public:
	PureBitmap(void);
  PureBitmap(const PureBitmap &somePureBitmap);
	PureBitmap(const String &strNameBitmap,HINSTANCE hInstance=GetModuleHandle(0));
	PureBitmap(const PureDevice &somePureDevice,const PureBitmap &somePureBitmap);
  PureBitmap(HBITMAP hBitmap);
	virtual ~PureBitmap();
	WORD loadBitmap(const String &strNameBitmap,HINSTANCE hInstance=::GetModuleHandle(0));
	BOOL compatibleBitmap(const PureDevice &somePureDevice,const PureBitmap &somePureBitmap);
	BOOL compatibleBitmap(const PureDevice &somePureDevice,int width,int height);
	BOOL compatibleBitmap(int width,int height);
	BOOL createFrom(PureBitmap &sourceBitmap,const Rect &srcRect);
  BOOL getInto(PureBitmap &dstBitmap,const Rect &rect)const;
  BOOL setFrom(PureBitmap &sourceBitmap,const Rect &rect)const;
	WORD screenBitmap(const RECT &boundingRect);
	WORD screenBitmap(const Rect &boundingRect);
  WORD windowBitmap(HWND hDisplayWindow);
  WORD operator==(const PureBitmap &somePureBitmap)const;
	WORD operator=(const PureBitmap &somePureBitmap);
	WORD operator=(HBITMAP hBitmap);
  bool getBitmapInfo(BitmapInfo &bmInfo);
  DWORD getBitmapBits(GlobalData<BYTE> &bitmapBytes,BOOL bottomUp=FALSE)const;
	DWORD getBitmapBits(GlobalData<BYTE> &bitmapBytes,BitmapInfo::BitsPerPixel bitsPerPixel,BOOL bottomUp=FALSE)const;
  DWORD getBitmapBits(GlobalData<BYTE> &bitmapBytes,BitmapInfo::BitsPerPixel bitsPerPixel,PurePalette &purePalette,BOOL bottomUp=FALSE)const;
  DWORD setBitmapBits(GlobalData<BYTE> &bitmapBytes,BOOL bottomUp=FALSE)const;
	WORD isOkay(void)const;
	operator HBITMAP(void)const;
	WORD width(void)const;
	WORD height(void)const;
	WORD widthBytes(void)const;
	WORD bitsPerPixel(void)const;
	HBITMAP getBitmap(void)const;
	void destroy(void);
private:
  void destroyBitmap(void);

	BITMAP mBitmap;
	HBITMAP mhBitmap;
};

inline
PureBitmap::PureBitmap(void)
: mhBitmap(0)
{
  ::memset(&mBitmap,0,sizeof(mBitmap));
}

inline
PureBitmap::PureBitmap(HBITMAP hBitmap)
: mhBitmap(0)
{
  ::memset(&mBitmap,0,sizeof(mBitmap));
  *this=hBitmap;
}

inline
PureBitmap::PureBitmap(const PureDevice &somePureDevice,const PureBitmap &somePureBitmap)
: mhBitmap(0)
{
	compatibleBitmap((HDC)somePureDevice,somePureBitmap);
}

inline
PureBitmap::PureBitmap(const PureBitmap &somePureBitmap)
: mhBitmap(0)
{
  *this=(PureBitmap&)somePureBitmap;
}

inline
PureBitmap::~PureBitmap()
{
  destroyBitmap();
}

inline
PureBitmap::operator HBITMAP(void)const
{
	return mhBitmap;
}

inline
void PureBitmap::destroyBitmap(void)
{
	if(mhBitmap){::DeleteObject(mhBitmap);mhBitmap=0;}
	::memset(&mBitmap,0,sizeof(mBitmap));
}

inline
WORD PureBitmap::isOkay(void)const
{
	return (mhBitmap?TRUE:FALSE);
}

inline
BOOL PureBitmap::compatibleBitmap(const PureDevice &somePureDevice,const PureBitmap &somePureBitmap)
{
  destroyBitmap();
	if(!somePureBitmap.isOkay())return FALSE;
	mhBitmap=::CreateCompatibleBitmap((HDC)somePureDevice,somePureBitmap.width(),somePureBitmap.height());
	if(mhBitmap)::GetObject(mhBitmap,sizeof(BITMAP),(LPSTR)&mBitmap);
	return isOkay();
}

inline
BOOL PureBitmap::compatibleBitmap(const PureDevice &somePureDevice,int width,int height)
{
	destroyBitmap();
  if(!somePureDevice.isOkay())return FALSE;
	mhBitmap=::CreateCompatibleBitmap((HDC)somePureDevice,width,height);
	if(mhBitmap)::GetObject(mhBitmap,sizeof(BITMAP),(LPSTR)&mBitmap);
	return isOkay();
}

inline
BOOL PureBitmap::compatibleBitmap(int width,int height)
{
  PureDevice pureDevice;
	pureDevice.displayDevice();
	return compatibleBitmap(pureDevice,width,height);
}

inline
WORD PureBitmap::width(void)const
{
	if(!isOkay())return FALSE;
	return mBitmap.bmWidth;
}

inline
WORD PureBitmap::widthBytes(void)const
{
  if(!isOkay())return FALSE;
	return mBitmap.bmWidthBytes;
}

inline
WORD PureBitmap::height(void)const
{
	if(!isOkay())return FALSE;
	return mBitmap.bmHeight;
}

inline
WORD PureBitmap::bitsPerPixel(void)const
{
  if(!isOkay())return FALSE;
	return mBitmap.bmBitsPixel;
}

inline
HBITMAP PureBitmap::getBitmap(void)const
{
  return mhBitmap;
}

inline
void PureBitmap::destroy(void)
{
  destroyBitmap();
}
#endif
