#include "stairs.h"
#include "dijkstra.h"
#include <stddef.h>

static int is_stair_candidate(uint8_t t) {
    return t == T_FLOOR; /* avoid corridors and doors so stairs sit in rooms */
}

/* Find the floor cell nearest to (cx,cy) in Chebyshev distance. */
static int nearest_floor(grid_t g, int cx, int cy, int *ox, int *oy) {
    int best = -1, bx = -1, by = -1;
    for (int y = 0; y < DROWS; y++) {
        for (int x = 0; x < DCOLS; x++) {
            if (!is_stair_candidate(g[y][x].terrain)) continue;
            int dx = x - cx, dy = y - cy;
            int d = (dx < 0 ? -dx : dx) + (dy < 0 ? -dy : dy);
            if (best < 0 || d < best) { best = d; bx = x; by = y; }
        }
    }
    if (best < 0) return 0;
    *ox = bx; *oy = by;
    return 1;
}

void place_stairs(grid_t g, event_sink_t *sink) {
    int ux, uy;
    if (!nearest_floor(g, DCOLS / 2, DROWS / 2, &ux, &uy)) return;
    g[uy][ux].terrain = T_STAIRS_UP;
    event_emit(sink, EV_STAIRS_PLACED_UP, NULL, 0);

    /* BFS from up-stair; pick farthest passable cell that is still a room
       floor candidate. */
    static dist_map_t dist;
    bfs_from(g, ux, uy, dist, -1, -1);

    int best_d = -1, dx_ = -1, dy_ = -1;
    for (int y = 0; y < DROWS; y++) {
        for (int x = 0; x < DCOLS; x++) {
            if (!is_stair_candidate(g[y][x].terrain)) continue;
            if (dist[y][x] == DIST_UNREACHABLE) continue;
            if (dist[y][x] > best_d) { best_d = dist[y][x]; dx_ = x; dy_ = y; }
        }
    }
    if (best_d < 0) return; /* degenerate: no other floor — leave down-stair unplaced */
    g[dy_][dx_].terrain = T_STAIRS_DOWN;
    event_emit(sink, EV_STAIRS_PLACED_DOWN, NULL, 0);
}
