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

static int is_passable(uint8_t t) {
    return t == T_FLOOR || t == T_CORRIDOR || t == T_DOOR;
}

int add_loops(grid_t g, event_sink_t *sink) {
    dist_map_t dist;
    int carved = 0;

    /* Iterate in a scan order so output is deterministic. */
    for (int y = 1; y < DROWS - 1; y++) {
        for (int x = 1; x < DCOLS - 1; x++) {
            if (g[y][x].terrain != T_NOTHING && g[y][x].terrain != T_WALL) continue;

            /* Two pairings: horizontal (E-W neighbors both passable) and
               vertical (N-S both passable). Require the OTHER axis to be
               impassable so we don't carve through corners. */
            int horiz = is_passable(g[y][x-1].terrain) && is_passable(g[y][x+1].terrain)
                     && !is_passable(g[y-1][x].terrain) && !is_passable(g[y+1][x].terrain);
            int vert  = is_passable(g[y-1][x].terrain) && is_passable(g[y+1][x].terrain)
                     && !is_passable(g[y][x-1].terrain) && !is_passable(g[y][x+1].terrain);
            if (!horiz && !vert) continue;

            int ax = horiz ? x - 1 : x;
            int ay = horiz ? y     : y - 1;
            int bx = horiz ? x + 1 : x;
            int by = horiz ? y     : y + 1;

            bfs_from(g, ax, ay, dist, -1, -1);
            int d = dist[by][bx];
            event_emit(sink, EV_LOOP_TESTED, NULL, 0);
            if (d >= LOOP_THRESHOLD && d < DIST_UNREACHABLE) {
                g[y][x].terrain = T_DOOR;
                g[y][x].flags |= F_IN_LOOP;
                carved++;
                event_emit(sink, EV_LOOP_ACCEPTED, NULL, 0);
            }
        }
    }
    return carved;
}
