#ifndef MAP_H
#define MAP_H

#ifdef CPC
#include <cpctelera.h>
#elif ALLEGRO5
#include <allegro5/allegro.h>
#include "SpriteUtil.h"
#endif

#include "GameState.h"
#include "GameTypes.h"
#include "MapManager.h"
#include "SpriteSet.h"

// The size of the back buffer.
#define BACKBUFFER_SIZE 256

// The default width of the back buffer (two cells wide).
#define BACKBUFFER_WIDTH 8

// The default height of the back buffer (two cells tall).
#define BACKBUFFER_HEIGHT 32

// Determine when a map redraw should happen.
extern u8 mapRedraw;

// The map grid.
extern u8 mapCells[MAP_CELL_COUNT];

// The back buffer where tiles and actors are combined before drawing.
extern u8 backbuffer[BACKBUFFER_SIZE];

// The actual width of the back buffer where tiles and actors are combined before drawing.
extern u8 backbufferWidth;

// The cell type used by default in the map grid and when clearing cells.
extern u8 defaultEnvironmentCell;

// Initialises the map grid.
void initMap(u8 levelNumber);

// Draws the contents of the map on screen.
void drawMap();

// Draws the content of a cell from the map on screen.
void drawCell(u8 x, u8 y, u8 cell);

// Retrieves a pointer to a graphic from a given cell value.
const u8* graphicFromCell(u8 cell);

#ifndef CPC
// Retrieves a pointer to an ALLEGRO_BITMAP from a given cell value.
ALLEGRO_BITMAP* allegroBitmapFromCell(u8 cell);
#endif

// Retrieve the index in the mapCell array for the given position (x,y) and room (x,y).
u16 mapCellPosition(u8 x, u8 y, u8 roomX, u8 roomY);

// Retrieve the cell from the mapCell array for the given position (x,y) and room (x,y).
u8 mapCell(u8 x, u8 y, u8 roomX, u8 roomY);

// Add the specified sprite to the backbuffer, dimensions are assumed to be the default TILE_WIDTH_BYTES * TILE_HEIGHT.
void addSpriteToBackbuffer(u8 x, u8 y, u8* sprite);

// Draws the content of the backbuffer at the specified location on the screen.
void drawBackbuffer(u8 x, u8 y);

// Populates the backbuffer with 4 cells from the map at the specified position.
void populateBackbufferFromMap(u8 cellX, u8 cellY);

// Draws the cell at the specified position in the map on screen.
void drawCellAtPosition(u8 x, u8 y);

// Updates the cell in the mapCell array at the given position (x,y) and room (x,y) and redraw the cell if it is in the current room.
void updateMapCellRedraw(u8 x, u8 y, u8 roomX, u8 roomY, u8 cell);

// Checks whether the cell contains the specified cell type (type must include flag).
u8 cellContainsType(u8 x, u8 y, u8 type);

#endif
