#ifndef _bitmap_h_
#define _bitmap_h_

#include <windows.h>
#include <assert.h>

typedef unsigned RGBX;

namespace Graphics
{

class Bitmap
{
public:
    Bitmap(int width, int height)
        : w(width), h(height), bits(0), handle(0), hDIB(0)
    {
        HDC dc = ::GetDC(NULL);
        handle = CreateCompatibleBitmap(dc, width, height);
        ::ReleaseDC(NULL, dc);
    }
    
    Bitmap(HBITMAP hBmp)
        : bits(0), handle(0), hDIB(0)
    {
        handle = hBmp;
        assert(handle);
        
        BITMAP bm;
        GetObject(handle, sizeof(BITMAP), &bm);
        w = bm.bmWidth;
        h = bm.bmHeight;
    }
    
    Bitmap(HINSTANCE hInstance, int resourceId)
        : bits(0), handle(0), hDIB(0)
    {
        handle = LoadBitmap(hInstance, MAKEINTRESOURCE(resourceId));
        assert(handle);

        BITMAP bm;
        GetObject(handle, sizeof(BITMAP), &bm);
        w = bm.bmWidth;
        h = bm.bmHeight;
    }
    
    Bitmap(RGBX* pixels, int width, int height)
        : handle(0), hDIB(0), w(width), h(height), bits(pixels)
    {
    }
    
    Bitmap(const WCHAR* fileName);
    
    Bitmap(HWND, int x, int y, int width, int height);
    
    Bitmap(Bitmap& b, int x, int y, int width, int height);
    
    virtual ~Bitmap()
    {
        if (handle)
            DeleteObject(handle);
        if (hDIB)
            DeleteObject(hDIB);
    }
    
    // alpha = 0 -> use pixel alpha 
    // else -> use alpha value, transparent color and opaque color
    // default transparent/opaque color = none
    void blend(Bitmap& b, int x, int y, unsigned char alpha = 0, unsigned transpColor = 0xFFFFFFFF,
        unsigned opaqueColor = 0xFFFFFFFF);
    
    void draw(HDC dc);
    
    void draw(HDC dc, int x, int y);
    
    void drawBits(HDC dc, int x, int y);
    
    static void drawBits(HDC dc, int x, int y, int w, int h, RGBX* pixels);
    
    RGBX* getBits();
    
    int getWidth() const
    {
        return w;
    }
    
    int getHeight() const
    {
        return h;
    }
    
    void reload()
    {
        if (bits && hDIB)
        {
            DeleteObject(hDIB);
            bits = NULL;
            getBits();
        }
    }
    
    operator HBITMAP() const
    {
        return handle;
    }
    
private:
    void capture(HDC dc, int x, int y);
    
public:
    static FILE* log;
protected:
    int w;
    int h;
    RGBX* bits;
    HBITMAP handle;
    HBITMAP hDIB;
    
    static HMODULE hShDll;
    typedef HBITMAP (*ImgLdFunc)(const WCHAR*);
    static ImgLdFunc SHLoadImageFile;
};

} // namespace Graphics

#endif // _bitmap_h_

