#ifndef _TPFMAP_H
#define _TPFMAP_H

#include "tex.h"
#include "vec.h"
#include "ang.h"

/* Contains code to manipulate a 2D map of textured blocks:
   * Each level is a 2d grid of blocks
   * Each block has 4 sides
   * Each side contains a wall type ID
   * Each level also contains a list of which wall ID corresponds to which
     texture, and flags on how to draw it */


/* Flags for wall definitions: */
/* Stop the ray caster when the wall is hit (i.e. texture isn't transparent) */
#define TPFWALL_STOPRAY 1
/* Draw the texture associated with the wall */
#define TPFWALL_TEXTURE 2


/* Maximum number of wall definitions per tpfMap
   Do not increase above 256 */
#define TPFMAP_MAXWALLS 64


/* Internal macro for calculating the index into the level map */
#define TPFMAP_CALCINDEX(M,X,Y) ((M->x*y)+X)


/* The sides of the blocks
   If you were outside a block, looking at its northern wall, then you would see
   the texture associated with side TPFMAP_WALL_N */
#define TPFMAP_WALL_N 0
#define TPFMAP_WALL_E 1
#define TPFMAP_WALL_S 2
#define TPFMAP_WALL_W 3


/* A couple of structures used internally */
typedef struct {
	int flags;
	tpfTex *s;
} tpfWall;

typedef struct {
	char w[4];
} tpfBlock;


/* Map structure
   Use the functions below as opposed to manipulating it directly */
typedef struct {
	int x,y;
	tpfVec org;
	tpfAng rot;
	tpfBlock *map;
	tpfWall walls[TPFMAP_MAXWALLS];
} tpfMap;

#ifdef __cplusplus
extern "C" {
#endif

/* Create a new, empty map of size x,y blocks
   x and y must be at least 1
   Dimensions over 128 or 256 may not be drawn correctly
   All block sides are initiated to wall ID 0
   All walls have no textures and are not solid */
extern tpfMap *TpfMap_New(int x,int y);

/* Delete a map */
extern void TpfMap_Delete(tpfMap *m);

/* Set side s of the block at x,y to wall ID c
   s must be one of the TPFMAP_WALL_* side numbers defined above
   c must be between 0 inclusive and TPFMAP_MAXWALLS exclusive
   if x or y are outside the map then nothing happens */
extern void TpfMap_SetSide(tpfMap *m,int x,int y,int s,int c);

/* Return the wall ID of side s of the block at x,y
   s must be one of the TPFMAP_WALL_* side numbers defined above
   if x or y are outside the map then 0 is returned */
extern int TpfMap_GetSide(tpfMap *m,int x,int y,int s);

/* Set the flags of wall id w to f
   w must be between 0 inclusive and TPFMAP_MAXWALLS exclusive
   f must be constructed from the TPFWALL_* bitflags defined above */
extern void TpfMap_SetWallFlags(tpfMap *m,int w,int f);

/* Set the texture of wall id w to t
   w must be between 0 inclusive and TPFMAP_MAXWALLS exclusive
   t can be null
   The texture is referenced by pointer; i.e. the original tpfTex must be left
   in existence */
extern void TpfMap_SetWallTex(tpfMap *m,int w,tpfTex *t);

/* Return the flags of wall id w
   w must be between 0 inclusive and TPFMAP_MAXWALLS exclusive */
extern int TpfMap_GetWallFlags(tpfMap *m,int w);

/* Return a pointer to the texture of wall id w
   w must be between 0 inclusive and TPFMAP_MAXWALLS exclusive */
extern tpfTex *TpfMap_GetWallTex(tpfMap *m,int w);

/* Set the location of the level origin */
extern void TpfMap_SetPos(tpfMap *m,tpfVec o);

/* Return the level origin */
extern tpfVec *TpfMap_GetPos(tpfMap *m);

/* Set the angle the level is drawn at
   The level is rotated around its bottom left corner */
extern void TpfMap_SetRot(tpfMap *m,tpfAng a);

/* Return the angle the level is drawn at */
extern tpfAng TpfMap_GetRot(tpfMap *m);

/* Return the width of the map */
extern int TpfMap_GetWidth(tpfMap *m);

/* Return the height of the map */
extern int TpfMap_GetHeight(tpfMap *m);

#ifdef __cplusplus
}
#endif 

#endif
