// The mutable local-game board: a 15x15 row-major grid of placed tiles (alphabet-index letter
// plus a blank flag). It satisfies the read view the validator and generator need (GenBoard,
// which extends validate.ts's Board) and adds set() so the engine can apply a play. The board is
// alphabet-agnostic — a cell's letter is a variant index, meaningful with the variant's ruleset.

import { BOARD_SIZE } from '../premiums';
import type { Cell } from '../dict/validate';
import type { GenBoard } from '../dict/generate';

/** LocalBoard is the engine's in-memory board; it reads as a GenBoard and applies plays via set. */
export class LocalBoard implements GenBoard {
  readonly rows = BOARD_SIZE;
  readonly cols = BOARD_SIZE;
  private readonly grid: (Cell | null)[];
  private count = 0;

  constructor() {
    this.grid = new Array<Cell | null>(BOARD_SIZE * BOARD_SIZE).fill(null);
  }

  inBounds(row: number, col: number): boolean {
    return row >= 0 && row < this.rows && col >= 0 && col < this.cols;
  }

  filled(row: number, col: number): boolean {
    return this.inBounds(row, col) && this.grid[row * this.cols + col] !== null;
  }

  cellAt(row: number, col: number): Cell {
    return this.grid[row * this.cols + col]!;
  }

  isEmpty(): boolean {
    return this.count === 0;
  }

  /** set places a tile at (row, col). It assumes the square was empty (a play only lays tiles
   *  on empty squares), keeping the filled count exact for isEmpty. */
  set(row: number, col: number, letter: number, blank: boolean): void {
    const i = row * this.cols + col;
    if (this.grid[i] === null) this.count++;
    this.grid[i] = { letter, blank };
  }
}
