#include "game/entity_registry.h"
#include "game/player.h"
#include "game/enemy.h"
#include "game/projectile.h"
#include "game/hazards.h"
#include "game/laser_turret.h"
#include "game/powerup.h"
#include "game/drone.h"
#include "game/spacecraft.h"
#include <string.h>
#include <stdio.h>

EntityRegistry g_entity_registry = {0};

/* ── Wrapper spawn functions ──────────────────────
 * Some spawn functions need extra args beyond (em, pos).
 * We wrap them to match the EntitySpawnFn signature.
 * ──────────────────────────────────────────────────── */

static Entity *spawn_platform_v(EntityManager *em, Vec2 pos) {
    return mplat_spawn_dir(em, pos, vec2(0.0f, 1.0f));
}

static Entity *spawn_powerup_health(EntityManager *em, Vec2 pos) {
    return powerup_spawn_health(em, pos);
}

static Entity *spawn_powerup_jetpack(EntityManager *em, Vec2 pos) {
    return powerup_spawn_jetpack(em, pos);
}

static Entity *spawn_powerup_fuel(EntityManager *em, Vec2 pos) {
    return powerup_spawn_fuel(em, pos);
}

static Entity *spawn_powerup_drone(EntityManager *em, Vec2 pos) {
    return powerup_spawn_drone(em, pos);
}

static Entity *spawn_powerup_gun(EntityManager *em, Vec2 pos) {
    return powerup_spawn_gun(em, pos);
}

static Entity *spawn_laser_track(EntityManager *em, Vec2 pos) {
    return laser_turret_spawn_tracking(em, pos);
}

/* ── Registry population ─────────────────────────── */

static void reg_add(const char *name, const char *display,
                    EntitySpawnFn fn, SDL_Color color, int w, int h,
                    int icon) {
    EntityRegistry *r = &g_entity_registry;
    if (r->count >= MAX_REGISTRY_ENTRIES) return;
    r->entries[r->count++] = (EntityRegEntry){
        .name     = name,
        .display  = display,
        .spawn_fn = fn,
        .color    = color,
        .width    = w,
        .height   = h,
        .icon     = icon,
    };
}

/* ── Registry table population (no EntityManager needed) ── */

void entity_registry_populate(void) {
    g_entity_registry.count = 0;

    /* ════════════════════════════════════════════
     *  REGISTRY TABLE
     *
     *  To add a new entity type to the game:
     *  1. Create its .h/.c files
     *  2. Register its behaviors in entity_registry_init()
     *  3. Add one reg_add() line below
     *
     *  The editor will pick it up automatically.
     * ════════════════════════════════════════════ */

    /*        .lvl name       display name     spawn fn              color (editor)                w   h   icon */
    reg_add("grunt",         "Grunt",          grunt_spawn,          (SDL_Color){200, 60, 60, 255},   GRUNT_WIDTH,   GRUNT_HEIGHT,    ICON_GRUNT);
    reg_add("flyer",         "Flyer",          flyer_spawn,          (SDL_Color){140, 80, 200, 255},  FLYER_WIDTH,   FLYER_HEIGHT,    ICON_FLYER);
    reg_add("turret",        "Turret",         turret_spawn,         (SDL_Color){160, 160, 160, 255}, TURRET_WIDTH,  TURRET_HEIGHT,   ICON_TURRET);
    reg_add("platform",      "Platform (H)",   mplat_spawn,          (SDL_Color){80, 180, 80, 255},   MPLAT_WIDTH,   MPLAT_HEIGHT,    ICON_PLATFORM);
    reg_add("platform_v",    "Platform (V)",   spawn_platform_v,     (SDL_Color){80, 160, 100, 255},  MPLAT_WIDTH,   MPLAT_HEIGHT,    ICON_PLATFORM_V);
    reg_add("flame_vent",    "Flame Vent",     flame_vent_spawn,     (SDL_Color){255, 120, 40, 255},  FLAME_WIDTH,   FLAME_HEIGHT,    ICON_FLAME);
    reg_add("force_field",   "Force Field",    force_field_spawn,    (SDL_Color){60, 140, 255, 255},  FFIELD_WIDTH,  FFIELD_HEIGHT,   ICON_FORCEFIELD);
    reg_add("powerup_hp",    "Health Pickup",  spawn_powerup_health, (SDL_Color){255, 80, 80, 255},   12, 12,                         ICON_HEART);
    reg_add("powerup_jet",   "Jetpack Refill", spawn_powerup_jetpack,(SDL_Color){255, 200, 50, 255},  12, 12,                         ICON_BOLT);
    reg_add("powerup_fuel",  "Jetpack Fuel",   spawn_powerup_fuel,  (SDL_Color){255, 150, 30, 255},  12, 12,                         ICON_FUEL);
    reg_add("powerup_drone", "Drone Pickup",   spawn_powerup_drone,  (SDL_Color){80, 200, 255, 255},  12, 12,                         ICON_DRONE);
    reg_add("powerup_gun",   "Gun Pickup",    spawn_powerup_gun,    (SDL_Color){200, 200, 220, 255}, 12, 12,                        ICON_GUN);
    reg_add("asteroid",      "Asteroid",      asteroid_spawn,       (SDL_Color){140, 110, 80, 255},  ASTEROID_WIDTH, ASTEROID_HEIGHT, ICON_ASTEROID);
    reg_add("spacecraft",    "Spacecraft",    spacecraft_spawn,     (SDL_Color){187, 187, 187, 255}, SPACECRAFT_WIDTH, SPACECRAFT_HEIGHT, ICON_SPACECRAFT);
    reg_add("laser_turret",  "Laser Turret",  laser_turret_spawn,   (SDL_Color){200, 80, 50, 255},   LASER_WIDTH,  LASER_HEIGHT,  ICON_LASER);
    reg_add("laser_turret_track", "Laser Track", spawn_laser_track, (SDL_Color){220, 100, 60, 255},  LASER_WIDTH,  LASER_HEIGHT,  ICON_LASER_TRACK);
    reg_add("charger",      "Charger",       charger_spawn,        (SDL_Color){220, 140, 40, 255},  CHARGER_WIDTH, CHARGER_HEIGHT, ICON_CHARGER);
    reg_add("spawner",      "Spawner",       spawner_spawn,        (SDL_Color){140, 50, 160, 255},  SPAWNER_WIDTH, SPAWNER_HEIGHT, ICON_SPAWNER);

    printf("Entity registry: %d types registered\n", g_entity_registry.count);
}

void entity_registry_init(EntityManager *em) {
    /* Populate the registry table first */
    entity_registry_populate();

    /* Register all entity behaviors with the entity manager */
    player_register(em);
    player_set_entity_manager(em);
    grunt_register(em);
    flyer_register(em);
    projectile_register(em);
    turret_register(em);
    mplat_register(em);
    flame_vent_register(em);
    force_field_register(em);
    powerup_register(em);
    drone_register(em);
    asteroid_register(em);
    spacecraft_register(em);
    laser_turret_register(em);
    charger_register(em);
    spawner_register(em);
}

const EntityRegEntry *entity_registry_find(const char *name) {
    for (int i = 0; i < g_entity_registry.count; i++) {
        if (strcmp(g_entity_registry.entries[i].name, name) == 0) {
            return &g_entity_registry.entries[i];
        }
    }
    return NULL;
}

Entity *entity_registry_spawn(EntityManager *em, const char *name, Vec2 pos) {
    const EntityRegEntry *entry = entity_registry_find(name);
    if (!entry) {
        fprintf(stderr, "entity_registry_spawn: unknown type '%s'\n", name);
        return NULL;
    }
    return entry->spawn_fn(em, pos);
}
