#ifndef PLAYER_H
#define PLAYER_H

#include "Actor.h"
#include "Difficulty.h"
#include "Environment.h"
#include "GameState.h"
#include "GameTypes.h"
#include "Interactable.h"
#include "Inventory.h"
#include "Item.h"
#include "Keys.h"
#include "Object.h"
#include "Palette.h"
#include "SpriteSet.h"
#include "Tile.h"

// The current player in the game.
typedef struct Player Player;

struct Player
{
    // Actor object containing position and velocity.
    Object object;

    // Number of hitpoints.
    u8 health;

    // Indicates whether the player should be redrawn on screen.
    u8 redraw;

    // The type of actor (player, enemy).
    u8 actorType;

    // The direction that the player is currently facing.
    u8 direction;

    // Detecting the environment cells the player is in.
    u8 environmentFlags;

    // Used for drawing the appropriate player sprite based on which palette index is applied for the player (player painted or not).
    u8 paletteOffset;
};

// Global player object.
extern Player player;

// The current environment flags set in the player.
extern u8 currentEnvironmentFlags;

// Environment flag for when the player is on chasm cells.
#define PLAYER_ENVIRONMENT_CHASM 1

// Environment flag for when the player is on a spike.
#define PLAYER_ENVIRONMENT_SPIKE 2

// Initialises the player struct with initial values.
void initPlayer(u8 x, u8 y);

// Draws the player on the screen as positioned in the player object.
void drawPlayer();

// Updates the player velocity based on user input.
void movePlayer();

// Player logic such as interactions and velocity/position.
void logicPlayer();

// Processes the cell in the current room that the player is potentially occupying.
u8 processCell(u8 x, u8 y);

// Processes the cell in the specified room that the player is potentially occupying.
u8 processCellInRoom(u8 x, u8 y, u8 roomX, u8 roomY);

// Moves the screen to a room on the x axis (left or right).
void moveRoomX(u8 newX, i8 roomDeltaX);

// Moves the player to the room below the current one.
void moveRoomBelow();

// Moves the player to the room above the current one.
void moveRoomAbove();

// Indicates whether the current colour of the player body matches the specified wall tile type.
u8 matchWallToBodyColourPalette(u8 tileType);

// Player has been damaged and will lose health and possible lives as a result.
void playerLoseHealth(u8 amount);

// Applies paint to the player by switching the player to secondary bright white and applying
// whatever colour is at the supplied palette colour index.
void paintPlayer(u8 paletteIndex);

// Match the spike colour to the current colour of the player body.
// If they do not match the environment spike flag will be returned to cause the playe to take damage.
u8 matchSpikeToBodyColourPalette(u8 paletteIndex);

// Updates the player environment flags on the player from where it is currently positioned within the room (also handles mines).
void updatePlayerEnvironmentFlags();

// Applies the player environment flags from the cell (if it is an environment cell) in the current room.
void calculateCellEnvironmentFlags(u8 x, u8 y);

#endif
