// Match-detection golden: run `find_matches` over several HAND-CRAFTED boards
// and snapshot the matched-cell set for each. Every board is built explicitly
// (no seeded init) on a checkerboard O/G background — which is itself run-free,
// since adjacent cells always differ — with the runs under test painted in the
// other gem colours. For each scene the board and its matched-cell dump are
// printed, and the matched-cell count is asserted independently of the dump.
#import "modules/std.sx";
#import "board.sx";
t :: #import "test.sx";

// Inverse of `gem_char`: map a gem character back to its Gem so each board can
// be written as a human-readable grid of GEM_CHARS.
char_to_gem :: (c: u8) -> Gem {
    for 0..GEM_COUNT: (i) {
        if GEM_CHARS[i] == c { return cast(Gem) i; }
    }
    .red
}

// Build a scene: load an 8x8 board from `rows` (top row first, each exactly
// BOARD_COLS gem characters), detect matches, print board + matched dump, and
// assert the matched-cell count.
scene :: (name: string, rows: []string, want_count: s64) {
    b : Board = ---;
    for 0..BOARD_ROWS: (row) {
        line := rows[row];
        for 0..BOARD_COLS: (col) {
            b.set(col, row, char_to_gem(line[col]));
        }
    }

    m := find_matches(@b);
    print("== {} ==\n", name);
    out(board_dump(@b));
    out("--\n");
    out(dump_matches(@b, @m));

    t.expect(m.count() == want_count, name);
}

main :: () -> s32 {
    // Single horizontal 3-run (row 3, cols 2-4).
    scene("horizontal-3", .[
        "OGOGOGOG",
        "GOGOGOGO",
        "OGOGOGOG",
        "GORRROGO",
        "OGOGOGOG",
        "GOGOGOGO",
        "OGOGOGOG",
        "GOGOGOGO",
    ], 3);

    // Single vertical 3-run (col 5, rows 2-4).
    scene("vertical-3", .[
        "OGOGOGOG",
        "GOGOGOGO",
        "OGOGOBOG",
        "GOGOGBGO",
        "OGOGOBOG",
        "GOGOGOGO",
        "OGOGOGOG",
        "GOGOGOGO",
    ], 3);

    // Multiple disjoint runs: horizontal R (row 1, cols 0-2), horizontal P
    // (row 5, cols 2-4), vertical Y (col 6, rows 4-6).
    scene("disjoint-runs", .[
        "OGOGOGOG",
        "RRROGOGO",
        "OGOGOGOG",
        "GOGOGOGO",
        "OGOGOGYG",
        "GOPPPOYO",
        "OGOGOGYG",
        "GOGOGOGO",
    ], 9);

    // A length-5 horizontal run (row 1, cols 1-5) and a length-4 vertical run
    // (col 7, rows 2-5).
    scene("len4-and-len5", .[
        "OGOGOGOG",
        "GRRRRRGO",
        "OGOGOGOB",
        "GOGOGOGB",
        "OGOGOGOB",
        "GOGOGOGB",
        "OGOGOGOG",
        "GOGOGOGO",
    ], 9);

    // Intersecting shapes, shared cell counted once: an L (R horizontal row 1
    // cols 1-3 meeting R vertical col 1 rows 1-3 at the corner (1,1)) and a T
    // (Y horizontal row 5 cols 3-5 meeting Y vertical col 4 rows 5-7 at the
    // mid/top cell (4,5)).
    scene("L-and-T", .[
        "OGOGOGOG",
        "GRRRGOGO",
        "OROGOGOG",
        "GRGOGOGO",
        "OGOGOGOG",
        "GOGYYYGO",
        "OGOGYGOG",
        "GOGOYOGO",
    ], 10);

    // No matches: the bare checkerboard, every adjacent pair differs.
    scene("no-matches", .[
        "OGOGOGOG",
        "GOGOGOGO",
        "OGOGOGOG",
        "GOGOGOGO",
        "OGOGOGOG",
        "GOGOGOGO",
        "OGOGOGOG",
        "GOGOGOGO",
    ], 0);

    print("ok: match detection over hand-crafted boards\n");
    return 0;
}
