#ifndef __PGGLIB_H__
#define __PGGLIB_H__

#include <inttypes.h>

#if __cplusplus
extern "C" {
#endif

// this is any kind of display
typedef struct PGG_Display_t *PGG_Display;

typedef struct PGS_Surface_t *PGS_Surface;
typedef struct PGG_RGBColor_t PGG_RGBColor;
typedef struct PGG_Rect_t PGG_Rect;

struct PGG_RGBColor_t
{
	uint8_t r;
	uint8_t g;
	uint8_t b;
	uint8_t a;
};
struct PGG_Rect_t
{
	int32_t l;
	int32_t t;
	int32_t r;
	int32_t b;
};

struct PGG_DisplayMode_t;
typedef struct PGG_DisplayMode_t PGG_DisplayMode;

struct PGG_DisplayMode_t
{
	int32_t width;
	int32_t height;
	int32_t windowed;
};

int32_t PGG_GetDisplayModeCount(void);
PGG_DisplayMode PGG_GetDisplayMode(int32_t index);

// The first thing we usually want to do is create the display.  We do this
// with PGG_DisplayCreate()...
PGG_Display PGG_DisplayCreate(const char *title,int32_t w,int32_t h,int32_t d);

// We also want to delete the display at the end.
void PGG_DisplayDelete(PGG_Display d);

// The first display created is stored in a global gDisplay variable.  If
// you're only using one display or window, you can either use gDisplay for
// any function requiring a PGG_Display paramater, or NULL.
extern PGG_Display gDisplay;

// Get the system-specific drawable for the given display. (PtWidget_t for
// QNX.)
void *PGG_DisplayDrawable(PGG_Display d);

// Once we've created the display, the next thing we usually want to do is
// show it, with PGG_DisplayShow().  This is also the function we use to
// hide the display.
void PGG_DisplayShow(PGG_Display d,int32_t show);

// You may want to modify the size, depth, or fullscreen/windowed mode.  
void PGG_DisplaySetWindowed(PGG_Display disp,int32_t windowed);
void PGG_DisplaySetScale(PGG_Display disp,int32_t scale);
void PGG_DisplaySetTitle(PGG_Display disp,const char *title);
void PGG_DisplaySetPosition(PGG_Display disp,int32_t x,int32_t y);

// You may want to query one or all of these values at some point as well:
int32_t PGG_DisplayWindowed(PGG_Display disp);
int32_t PGG_DisplayScale(PGG_Display disp);
void PGG_DisplayPosition(PGG_Display d,int32_t *x,int32_t *y);

// To actually do something with the contents of the display, we need some
// way to acquire the display buffer, modify it, and blit it...
//
// First, we get the display's surface with PGG_DisplaySurface().  This pointer
// is guaranteed to be always valid, but its contents won't be unless you've
// acquired the surface using the PGG_DisplaySurfaceLock() function.  Once 
// you've acquired a surface, you can change the surface data (pointed to by 
// the bits field) as int32_t as you stay within wb*h bytes of the bits pointer.
// Once you're finished modifying the surface, you should call 
// PGG_DisplaySurfaceUnlock().  If you've modified the display's surface data 
// during the time you had it acquired, you should call 
// PGG_DisplaySurfaceDirty() to mark which area needs to be updated on the next
// PGG_DisplayBlit() call.  Finally, call PGG_DisplayBlit() to blit the surface
// to the display.
PGS_Surface PGG_DisplaySurface(PGG_Display d);
int32_t PGG_DisplayLock(PGG_Display d);
void PGG_DisplayDirty(PGG_Display,int32_t x,int32_t y,int32_t w,int32_t h);
void PGG_DisplayUnlock(PGG_Display d);
void PGG_DisplayBlit(PGG_Display d);

// If you create a 8 bit display, you'll need to set your palette.  You can
// do this with the PGG_DisplaySetPalette() function call.  If you need to
// get the current palette, call the PGG_DisplayGetPalette() function.  In
// either case, the colors paramater should point to a 256 element array.
void PGG_DisplaySetPalette(PGG_Display d,PGG_RGBColor *colors);
void PGG_DisplayGetPalette(PGG_Display d,PGG_RGBColor *colors);

// We can set a number of callbacks for events that occur. (Note that these
// have to be called for every display instance (ie multiple windows) you
// have.
//
// When the system determines that part of the display needs to be redrawn,
// it calls the Redraw callback, set in this function:
void PGG_SetCBRedraw(PGG_Display d,void (*cb)(PGG_Display d,PGG_Rect ur));

// When the windows close button is pressed, this callback will be called if
// it is set.
void PGG_SetCBClose(PGG_Display d,void (*cb)(PGG_Display d));

// Display's Surface functions:
void *PGG_DisplayBits(PGG_Display d);
int32_t PGG_DisplayWidth(PGG_Display d);
int32_t PGG_DisplayHeight(PGG_Display d);
int32_t PGG_DisplayDepth(PGG_Display d);
int32_t PGG_DisplayWidthBytes(PGG_Display d);

// Cursor function:
//
// You may want to enable/disable the cursor while we're in the game display.
void PGG_CursorShow(PGG_Display d,int32_t show);

// You may want to move the cursor to a given position in your display area:
void PGG_CursorSetPos(PGG_Display d,int32_t x,int32_t y);

int32_t PGG_CursorPos(PGG_Display d,int32_t *x,int32_t *y);

// We have some build-in functions to make updating the video buffer (or
// even internal buffers) easier.
//
// The first are simply optimized rectangular area copy functions:
void PGG_AreaCopy8(void *src,int32_t sx,int32_t sy,int32_t swb,void *dst,int32_t dx,int32_t dy,int32_t dwb,int32_t w,int32_t h);

#if __cplusplus
};
#endif

#endif

