#include "events.h"
#include <stddef.h>

void event_emit(event_sink_t *sink, event_kind_t kind,
                const cell_diff_t *diffs, uint32_t diff_count) {
    if (!sink || !sink->fn) return;
    gen_event_t ev = {0};
    ev.step = sink->step++;
    ev.kind = (uint16_t)kind;
    ev.diffs = (cell_diff_t *)diffs;
    ev.diff_count = diff_count;
    sink->fn(sink->ctx, &ev);
}

const char *event_kind_name(event_kind_t k) {
    switch (k) {
        case EV_GEN_BEGIN: return "GEN_BEGIN";
        case EV_ROOM_PROPOSED: return "ROOM_PROPOSED";
        case EV_ROOM_PLACED: return "ROOM_PLACED";
        case EV_ROOM_REJECTED: return "ROOM_REJECTED";
        case EV_DOOR_SITE_CHOSEN: return "DOOR_SITE_CHOSEN";
        case EV_CORRIDOR_CARVED: return "CORRIDOR_CARVED";
        case EV_LOOP_TESTED: return "LOOP_TESTED";
        case EV_LOOP_ACCEPTED: return "LOOP_ACCEPTED";
        case EV_CA_ITERATION: return "CA_ITERATION";
        case EV_LAKE_PROPOSED: return "LAKE_PROPOSED";
        case EV_LAKE_REJECTED_IMPASSABLE: return "LAKE_REJECTED_IMPASSABLE";
        case EV_LAKE_PLACED: return "LAKE_PLACED";
        case EV_WREATH_APPLIED: return "WREATH_APPLIED";
        case EV_BRIDGE_PLACED: return "BRIDGE_PLACED";
        case EV_WALLS_FINISHED: return "WALLS_FINISHED";
        case EV_STAIRS_PLACED_UP: return "STAIRS_PLACED_UP";
        case EV_STAIRS_PLACED_DOWN: return "STAIRS_PLACED_DOWN";
        case EV_CHOKEPOINT_FOUND: return "CHOKEPOINT_FOUND";
        case EV_MACHINE_PROPOSED: return "MACHINE_PROPOSED";
        case EV_BLUEPRINT_CASCADE_BEGIN: return "BLUEPRINT_CASCADE_BEGIN";
        case EV_FEATURE_BUILT: return "FEATURE_BUILT";
        case EV_MACHINE_ACCEPTED: return "MACHINE_ACCEPTED";
        case EV_MACHINE_RESTORED_ON_FAIL: return "MACHINE_RESTORED_ON_FAIL";
        case EV_GEN_END: return "GEN_END";
        default: return "?";
    }
}

const char *event_kind_what(event_kind_t k) {
    switch (k) {
        case EV_GEN_BEGIN:                return "Phase 0: empty grid";
        case EV_ROOM_PROPOSED:            return "Phase 1: trying a room";
        case EV_DOOR_SITE_CHOSEN:         return "Phase 1: door site picked";
        case EV_CORRIDOR_CARVED:          return "Phase 1: corridor carved";
        case EV_ROOM_PLACED:              return "Phase 1: room placed";
        case EV_ROOM_REJECTED:            return "Phase 1: room gave up";
        case EV_LOOP_TESTED:              return "Phase 2: testing a loop";
        case EV_LOOP_ACCEPTED:            return "Phase 2: loop punched";
        case EV_CA_ITERATION:             return "Phase 3: CA smoothing step";
        case EV_LAKE_PROPOSED:            return "Phase 3: lake proposed";
        case EV_LAKE_REJECTED_IMPASSABLE: return "Phase 3: lake rejected";
        case EV_LAKE_PLACED:              return "Phase 3: lake placed";
        case EV_WREATH_APPLIED:           return "Phase 3: shorelines marked";
        case EV_BRIDGE_PLACED:            return "Phase 3: bridge laid";
        case EV_WALLS_FINISHED:           return "Phase 4: walls finished";
        case EV_STAIRS_PLACED_UP:         return "Phase 5: up-stair placed";
        case EV_STAIRS_PLACED_DOWN:       return "Phase 5: down-stair placed";
        case EV_CHOKEPOINT_FOUND:         return "Phase 6: chokepoint found";
        case EV_MACHINE_PROPOSED:         return "Phase 6: machine proposed";
        case EV_BLUEPRINT_CASCADE_BEGIN:  return "Phase 6: cascade begins";
        case EV_FEATURE_BUILT:            return "Phase 6: feature built";
        case EV_MACHINE_ACCEPTED:         return "Phase 6: machine accepted";
        case EV_MACHINE_RESTORED_ON_FAIL: return "Phase 6: machine rolled back";
        case EV_GEN_END:                  return "Done";
        default: return "";
    }
}

const char *event_kind_why(event_kind_t k) {
    switch (k) {
        case EV_GEN_BEGIN:
            return "Bare 79x29 grid. Phases run in order: rooms -> loops -> lakes -> walls.";
        case EV_ROOM_PROPOSED:
            return "Carved a candidate room in scratch space. Searching for a place to attach it.";
        case EV_DOOR_SITE_CHOSEN:
            return "An existing room has a perimeter cell facing empty space - that's the doorway.";
        case EV_CORRIDOR_CARVED:
            return "Vertical corridors are 2-9 cells, horizontal 5-15. Connects the candidate to the existing dungeon.";
        case EV_ROOM_PLACED:
            return "Buffer + corridor checks passed. Map remains fully connected by construction.";
        case EV_ROOM_REJECTED:
            return "After 30 attempts, no valid attachment was found. Move on.";
        case EV_LOOP_TESTED:
            return "Wall with passable cells on opposite sides. If their shortest path is far apart, a shortcut helps.";
        case EV_LOOP_ACCEPTED:
            return "Graph distance >= 20. Punching the wall creates a useful loop in the dungeon.";
        case EV_CA_ITERATION:
            return "Cellular automata smoothing the lake blob: B678/S45678 rule, 5 iterations total.";
        case EV_LAKE_PROPOSED:
            return "Blue overlay = where the lake would go. Red overlay = cells that would become unreachable.";
        case EV_LAKE_REJECTED_IMPASSABLE:
            return "Lake would orphan part of the map. Reject and try a smaller bounding box.";
        case EV_LAKE_PLACED:
            return "Passability test passed. Lake painted onto the map; connectivity preserved.";
        case EV_WREATH_APPLIED:
            return "Cells adjacent (8-conn) to liquid are tagged shoreline. Used later for visual variety.";
        case EV_BRIDGE_PLACED:
            return "Found a floor-liquid-floor span <= 5 cells. Liquid replaced with a bridge.";
        case EV_WALLS_FINISHED:
            return "Polish pass: every empty cell next to any open terrain becomes a wall.";
        case EV_STAIRS_PLACED_UP:
            return "Up-stair placed at the first room's center - the level's entry point.";
        case EV_STAIRS_PLACED_DOWN:
            return "Down-stair placed at the floor cell with the longest graph-distance from the up-stair.";
        case EV_CHOKEPOINT_FOUND:
            return "Articulation point: if blocked, part of the map becomes unreachable. Ideal vestibule candidate.";
        case EV_MACHINE_PROPOSED:
            return "A blueprint is being tried. Looking for a chokepoint or room that matches the constraints.";
        case EV_BLUEPRINT_CASCADE_BEGIN:
            return "Reward rooms may spawn vestibules, which may spawn key-guard machines - a cascade of nested blueprints.";
        case EV_FEATURE_BUILT:
            return "A single feature within the current blueprint was placed (terrain / item marker / monster marker).";
        case EV_MACHINE_ACCEPTED:
            return "All required features fit. Machine committed; any nested cascades ran successfully.";
        case EV_MACHINE_RESTORED_ON_FAIL:
            return "Placement couldn't satisfy all constraints. Level state is rolled back to before the attempt.";
        case EV_GEN_END:
            return "Final dungeon. Every passable cell is 4-connected to every other - Brogue's invariant.";
        default: return "";
    }
}
