/*
 * Main.h - Header included by all code files
 * By: Odis
 */
#ifndef INC_MAIN
#define INC_MAIN

/* normal defines */
/* for ease of use */
#if !defined(MSL)
#define MSL 5120
#endif

#if !defined(MIL)
#define MIL 1024
#endif

#if !defined(TRUE)
#define TRUE 1
#endif

#if !defined(FALSE)
#define FALSE 0
#endif

#if !defined(ERROR)
#define ERROR -1
#endif

#if !defined(DEF_BOOL)
typedef short int		        bool;
#define DEF_BOOL 1
#endif
/* end of normal defines */

/* we have the defines, now lets get the rest in here */
#include <xlog.h>
#include <bitmask.h>

#include "bits.h"
#include "bitmap.h"
#include "resource.h"
#include "sprite.h"
#include "sound.h"
#include "bg.h"
#include "level.h"

/* structs */
struct game_data
{
  HINSTANCE     hInstance;
  HWND          hWindow;
  
  BMP *         first_bmp; /* keep track of the games current bitmaps */
  BMP *         last_bmp;
  
  int           current_level;
  int           width;
  int           height;
  int           framedelay; /* for fps */
  bool          sleep;
};

/* player struct */
struct player_data
{
   char   *name;
   int     score;
   int     health;
   int     lives;
};

/* end of structs */


/* struct typedefs */
typedef struct player_data PLAYER_DATA;
typedef struct game_data GAME;

/* end of struct typedefs */

/* global variables, functions, etc. */

/* Init.c */
bool init_game( HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int iCmdShow);
LRESULT handle_event( HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam );

void SetWindow( HWND hWnd );
void SetFrameRate( int rate );
void SetSleep( bool bSleep );

/* Game.c */
void game_loop( void );
void game_paint(HDC hDC);
void game_start(HWND hWindow);
void game_end( void );
void game_activate( void );
void game_deactivate( void );
void handle_keys( void );
void DodgeAI( SPRITE *sprite );
void game_size( LONG x, LONG y, LEVEL *l );

void mousemove(int x, int y);
void mousebuttondown( int x, int y, bool left );
void mousebuttonup(int x, int y, bool left);

int random( int low, int high );

/* bitmap.c */
void clean_bitmaps(GAME *g);

/* functions.c */
char *read_word( char *string1 );
char *strip_spaces(char *buf);
char *strrep( const char *src, const char *sch, const char *rep, char *die );
char *strip_leading_spaces(char *buf);
bool is_number( char *num );

/* sprite.c */
SPRITE *get_proto ( char *name, LEVEL *level );
SPRITE *get_sprite( char *name, LEVEL *level );

bool SpriteCollisionObj( OBJ *obj, SPRITE *sprite );
bool CheckSpriteCollisionObj(SPRITE *sprite);
bool TestCollisionObj( SPRITE *sprite, OBJ *obj );

/* bg.c */
void bg_update( LEVEL *level );
void bg_draw( LEVEL *level, HDC hDC );

/* externs */
extern GAME *game;
extern PLAYER_DATA *player;

/* level.c */
extern unsigned char level_buf[LEVELS][MSL];
/* end externs */

/* thanks to SMAUG for the macro's */
/* ah...memory macro's */
#define CREATE(result, type, number)					\
do											\
{											\
    if (!((result) = (type *) calloc ((number), sizeof(type))))	\
    {											\
	perror("malloc failure");						\
	abort();									\
    }											\
} while(0)

#define DISPOSE(point) 								\
do											\
{											\
   if((point))									\
   {											\
	free((point));								\
	(point) = NULL;								\
   }											\
} while(0)

/* doublely-linked list handling */
#define LINK(link, first, last, next, prev)                     	\
do                                                              	\
{                                                               	\
   if ( !(first) )								\
   {                                           				\
      (first) = (link);				                       	\
      (last) = (link);							    	\
   }											\
   else                                                      	\
      (last)->next = (link);			                       	\
   (link)->next = NULL;			                         	\
   if (first == link)								\
      (link)->prev = NULL;							\
   else										\
      (link)->prev = (last);			                       	\
   (last) = (link);				                       	\
} while(0)

#define INSERT(link, insert, first, next, prev)                 \
do                                                              \
{                                                               \
   (link)->prev = (insert)->prev;			                \
   if ( !(insert)->prev )                                       \
      (first) = (link);                                         \
   else                                                         \
      (insert)->prev->next = (link);                            \
   (insert)->prev = (link);                                     \
   (link)->next = (insert);                                     \
} while(0)

#define UNLINK(link, first, last, next, prev)                   	\
do                                                              	\
{                                                               	\
	if ( !(link)->prev )							\
	{			                                    	\
         (first) = (link)->next;			                 	\
	   if ((first))							 	\
	      (first)->prev = NULL;						\
	} 										\
	else										\
	{                                                 		\
         (link)->prev->next = (link)->next;                 	\
	}										\
	if ( !(link)->next ) 							\
	{				                                    \
         (last) = (link)->prev;                 			\
	   if ((last))								\
	      (last)->next = NULL;						\
	} 										\
	else										\
	{                                                    		\
         (link)->next->prev = (link)->prev;                 	\
	}										\
} while(0)

/* utility macro's */
#define UMIN(a, b)		((a) < (b) ? (a) : (b))
#define UMAX(a, b)		((a) > (b) ? (a) : (b))
#define URANGE(a, b, c)		((b) < (a) ? (a) : ((b) > (c) ? (c) : (b)))


/* this should be in game.h, but i dont want to include game.h with every file */
extern LONG PRG_WIDTH;
extern LONG PRG_HEIGHT;

#define PRG_DEFAULT_FPS  60

#endif