#pragma once

#include <SDL2/SDL.h>
#include "actor.h"
#include "common/animatedsprite.h"
#include "common/asset.h"
#include "common/debug.h"
#include "common/input.h"
#include "common/jail_audio.h"
#include "common/utils.h"
#include "map.h"

#ifndef PLAYER_H
#define PLAYER_H

enum e_state
{
	s_standing,
	s_jumping,
	s_falling
};

enum e_living
{
	l_alive,
	l_dying,
	l_dead
};

enum e_floor
{
	f_none,
	f_wall,
	f_platform
};

struct player_t
{
	float x;
	float y;
	float vx;
	float vy;
	e_state state;
	SDL_RendererFlip flip;
};

// The player
class Player
{
private:
	Asset *asset;			// Objeto con la ruta a todos los ficheros de recursos
	SDL_Renderer *renderer; // El renderizador de la ventana
	Input *input;			// Objeto Input para gestionar las entradas
	AnimatedSprite *sprite; // Objeto con los graficos, animaciones y posición del jugador
	LTexture *texture;		// Textura con los graficos del jugador
	Map *map;				// Objeto con el mapa
	Debug *debug;			// Objeto para gestionar la información de debug

	float x;					// Posición del jugador en el eje X
	float y;					// Posición del jugador en el eje Y
	float vx;					// Velocidad/desplazamiento del jugador en el eje X
	float vy;					// Velocidad/desplazamiento del jugador en el eje Y
	int w;						// Ancho del jugador
	int h;						// ALto del jugador
	e_state state;				// Estado actual del jugador
	e_border border;			// Indica en qué borde de la pantalla está el jugador
	e_living living;			// Indica en que estado de la vida se encuentra el jugador
	SDL_Point lastPosition;		// Posición anterior
	int hookedOnMovingPlatform; // Índice de la plataforma movil a la que está enganchado
	e_floor isOn;				// Indica sobre que tipo de suelo se encuentra
	SDL_Rect colliderBox;		// Caja de colisión

	// Variables que afectan a la inercia del movimiento
	bool jumpPressed;	// Indica si esta pulsada la tecla de salto
	float jumpStrenght; // Cantidad de pixels a desplazarse y velocidad que pilla al saltar
	float gravity;		// Gravedad
	float accelX;		// Aceleración al desplazarse horizontalmente
	float maxVX;		// Velocidad mazima de desplazamiento horizontal
	float maxVY;		// Velocidad mazima de desplazamiento vertical

	int *diamonds;					  // Puntero a la cantidad de diamantes recogidos y que lleva la cuenta el juego
	std::vector<bool> key;			  // Indica las llaves que posee el jugador
	std::vector<SDL_Point> collider;  // Contiene los puntos de colisión del jugador con el mapa
	std::vector<SDL_Point> underFeet; // Contiene los puntos que hay bajo cada pie del jugador
	JA_Sound sound_coin;			  // Sonido al coger monedas
	JA_Sound sound_death;			  // Sonido al morir
	JA_Sound sound_jump;			  // Sonido al saltar

	// Comprueba las entradas y modifica variables
	void checkInput();

	// Comprueba los estados de vida
	void checkLivingState();

	// Aplica la gravedad
	void addGravity();

	// Actualiza los puntos de colisión
	void updateColliders();

	// Actualiza los puntos de los pies
	void updateFeet();

	// Compruena las colisiones con el mapa
	bool checkMapCollisions();

	// Mueve al jugador en función de la velocidad/desplazamiento
	void move();

	// Anima al jugador
	void animate();

	// Comprueba si el jugador tiene suelo debajo de los pies
	bool isOnFloor();

	// Comprueba si el jugador tiene una plataforma movil bajo sus pies
	bool isOnMovingPlatform();

	// Comprueba las interacciones con los actores
	int checkActors();

public:
	// Constructor
	Player(player_t player, SDL_Renderer *renderer, Asset *asset, Input *input, Map *map, Debug *debug, int *diamonds);

	// Destructor
	~Player();

	// Actualiza todas las variables
	void update();

	// Dibuja el objeto
	void render();

	// Comprueba si está situado en alguno de los cuatro bordes de la habitación
	bool isOnScreenBorder();

	// Devuelve el valor de la variable
	e_border getBorder();

	// Cambia al jugador de un borde al opuesto. Util para el cambio de pantalla
	void switchBorders();

	// Pasa la referencia del mapa
	void setMap(Map *map);

	// Recarga las texturas
	void reLoadTextures();

	// Devuelve el rectangulo que contiene al jugador
	SDL_Rect getRect();

	// Obtiene el rectangulo de colision del jugador
	SDL_Rect &getCollider();

	// Establece el estado de vida del jugador
	void setLivingState(e_living value);

	// Obtiene el estado de vida del jugador
	e_living getLivingState();

	// Obtiene algunos parametros del jugador
	player_t getSpawnParams();
};

#endif
