#ifndef JNR_PLAYER_H
#define JNR_PLAYER_H

#include "engine/entity.h"
#include "engine/camera.h"
#include "engine/tilemap.h"

/* Player physics tuning */
#define PLAYER_SPEED       150.0f   /* horizontal speed (px/s)       */
#define PLAYER_ACCEL       1200.0f  /* ground acceleration           */
#define PLAYER_DECEL       1600.0f  /* ground deceleration (friction)*/
#define PLAYER_AIR_ACCEL   600.0f   /* air acceleration              */
#define PLAYER_JUMP_FORCE  320.0f   /* initial jump velocity         */
#define PLAYER_JUMP_CUT    0.4f     /* multiplier when releasing jump*/
#define PLAYER_COYOTE_TIME 0.08f    /* seconds after leaving edge    */
#define PLAYER_JUMP_BUFFER 0.1f     /* seconds before landing        */

#define PLAYER_WIDTH  12
#define PLAYER_HEIGHT 16

/* Sprite dimensions (art is larger than hitbox) */
#define PLAYER_SPRITE_W 24
#define PLAYER_SPRITE_H 24
#define PLAYER_DEATH_SPRITE_W 32
#define PLAYER_DEATH_SPRITE_H 32

/* Shooting */
#define PLAYER_SHOOT_COOLDOWN 0.12f /* seconds between shots         */

/* Dash / Jetpack */
#define PLAYER_DASH_SPEED    350.0f /* dash velocity (px/s)          */
#define PLAYER_DASH_DURATION 0.15f  /* seconds the dash lasts        */
#define PLAYER_DASH_MAX_CHARGES  3  /* max jetpack charges           */
#define PLAYER_DASH_RECHARGE 30.0f  /* seconds to recharge one charge*/

/* Jetpack boost (from powerup) */
#define PLAYER_JETPACK_BOOST_DURATION 15.0f /* seconds the boost lasts    */
#define PLAYER_JETPACK_BOOST_RECHARGE  0.5f /* boosted recharge rate (s)  */

/* Invincibility after taking damage */
#define PLAYER_INV_TIME 1.5f       /* seconds of invincibility      */

/* Aim direction (for shooting) */
typedef enum AimDir {
    AIM_FORWARD,       /* horizontal, based on facing     */
    AIM_UP,            /* straight up                     */
    AIM_DIAG_UP,       /* 45 degrees up + forward         */
} AimDir;

typedef struct PlayerData {
    float   coyote_timer;
    float   jump_buffer_timer;
    bool    jumping;
    bool    was_on_ground;         /* on_ground last frame (landing detect) */
    float   shoot_cooldown;
    float   inv_timer;             /* invincibility timer           */
    /* Dash / Jetpack */
    float   dash_timer;            /* remaining dash time (0=not dashing) */
    int     dash_charges;          /* available jetpack charges      */
    int     dash_max_charges;      /* max charges (for HUD)         */
    float   dash_recharge_timer;   /* time until next charge restored*/
    Vec2    dash_dir;              /* direction of current dash     */
    float   jetpack_boost_timer;   /* remaining boost time (0=off)  */
    /* Weapon */
    bool    has_gun;               /* false until gun powerup picked up */
    /* Aiming */
    AimDir  aim_dir;               /* current aim direction         */
    bool    looking_up;            /* holding up without moving     */
    float   look_up_timer;         /* how long up has been held     */
    /* Death / Respawn */
    float   respawn_timer;         /* countdown after death anim finishes */
    Vec2    spawn_point;           /* where to respawn              */
} PlayerData;

/* Register player entity type with the entity manager */
void player_register(EntityManager *em);

/* Entity callbacks */
void player_update(Entity *self, float dt, const Tilemap *map);
void player_render(Entity *self, const Camera *cam);
void player_destroy(Entity *self);

/* Spawn a fully configured player entity */
Entity *player_spawn(EntityManager *em, Vec2 pos);

/* Set the entity manager the player lives in (for spawning projectiles) */
void player_set_entity_manager(EntityManager *em);

/* Get the player's current look-up offset for the camera */
float player_get_look_up_offset(const Entity *self);

/* Get jetpack dash charge info for HUD (returns false if entity is not player) */
bool player_get_dash_charges(const Entity *self, int *charges, int *max_charges,
                             float *recharge_pct, bool *boosted);

/* Arm the player (give them the gun). Safe to call multiple times. */
void player_give_gun(Entity *self);

/* Check if the player has a gun */
bool player_has_gun(const Entity *self);

/* Check if the player is requesting a respawn (death anim finished + timer expired).
 * Returns true when respawn should occur. */
bool player_wants_respawn(const Entity *self);

/* Reset the player to alive state at the given position */
void player_respawn(Entity *self, Vec2 pos);

#endif /* JNR_PLAYER_H */
