#ifndef JNR_TILEMAP_H
#define JNR_TILEMAP_H

#include <SDL2/SDL.h>
#include <stdbool.h>
#include <stdint.h>
#include <math.h>
#include "config.h"
#include "util/vec2.h"

/* Forward declarations */
typedef struct Camera Camera;

typedef enum TileFlag {
    TILE_SOLID    = 1 << 0,
    TILE_PLATFORM = 1 << 1,    /* one-way, passable from below  */
    TILE_LADDER   = 1 << 2,
    TILE_HAZARD   = 1 << 3,    /* spikes, lava, etc.            */
    TILE_WATER    = 1 << 4,
} TileFlag;

typedef struct TileDef {
    uint16_t tex_x, tex_y;     /* position in tileset (in tiles) */
    uint32_t flags;
} TileDef;

/* Entity spawn entry read from .lvl files */
typedef struct EntitySpawn {
    char     type_name[32];    /* e.g. "grunt", "flyer"          */
    float    x, y;             /* world position (pixels)        */
} EntitySpawn;

/* Exit zone — triggers level transition on player overlap */
typedef struct ExitZone {
    float    x, y, w, h;                    /* world-space bounding box    */
    char     target[ASSET_PATH_MAX];        /* path to next level, or
                                             * "generate" for procgen,
                                             * or empty for "you win"      */
} ExitZone;

typedef struct Tilemap {
    int          width, height;     /* map size in tiles          */
    uint16_t    *bg_layer;          /* background tile IDs        */
    uint16_t    *collision_layer;   /* solid geometry tile IDs    */
    uint16_t    *fg_layer;          /* foreground decoration IDs  */
    TileDef      tile_defs[MAX_TILE_DEFS];
    int          tile_def_count;
    SDL_Texture *tileset;
    int          tileset_cols;      /* columns in tileset image   */
    char         tileset_path[ASSET_PATH_MAX]; /* tileset file path */
    Vec2         player_spawn;
    float        gravity;           /* level gravity (px/s^2), 0 = use default */
    float        wind;              /* horizontal wind force (px/s^2), +=right  */
    char         music_path[ASSET_PATH_MAX]; /* level music file path          */
    SDL_Color    bg_color;          /* background clear color                  */
    bool         has_bg_color;      /* true if BG_COLOR was set                */
    char         parallax_far_path[ASSET_PATH_MAX];  /* far bg image path     */
    char         parallax_near_path[ASSET_PATH_MAX]; /* near bg image path    */
    int          parallax_style;    /* procedural bg style (0=default)         */
    bool         player_unarmed;   /* if true, player starts without gun       */
    EntitySpawn  entity_spawns[MAX_ENTITY_SPAWNS];
    int          entity_spawn_count;
    ExitZone     exit_zones[MAX_EXIT_ZONES];
    int          exit_zone_count;
} Tilemap;

bool     tilemap_load(Tilemap *map, const char *path, SDL_Renderer *renderer);
void     tilemap_render_layer(const Tilemap *map, const uint16_t *layer,
                              const Camera *cam, SDL_Renderer *renderer);
bool     tilemap_is_solid(const Tilemap *map, int tile_x, int tile_y);
uint32_t tilemap_flags_at(const Tilemap *map, int tile_x, int tile_y);
void     tilemap_free(Tilemap *map);

/* World-pixel to tile coordinate helpers */
static inline int world_to_tile(float world_coord) {
    return (int)floorf(world_coord / TILE_SIZE);
}

static inline float tile_to_world(int tile_coord) {
    return (float)(tile_coord * TILE_SIZE);
}

#endif /* JNR_TILEMAP_H */
