// Board premium layout — the 15x15 premium-square geometry, ported from the engine source
// of truth, scrabble-solver/rules/rules.go (standardBoard / eruditBoard). The board is not
// transmitted on the wire (StateView has no board), so the client renders the premiums
// locally; only the centre differs by variant. A Vitest parity test pins the geometry.
// Tile values and the alphabet come from the server-sent per-variant table (see
// lib/alphabet.ts), so this file is geometry only.

import type { Variant } from './model';

export const BOARD_SIZE = 15;

export type Premium = '' | 'TW' | 'DW' | 'TL' | 'DL';

// Legend (rules.go): T=triple word, D=double word, t=triple letter, d=double
// letter, .=plain, *=centre (a double word), +=centre with no premium.
const standardBoard = [
  'T..d...T...d..T',
  '.D...t...t...D.',
  '..D...d.d...D..',
  'd..D...d...D..d',
  '....D.....D....',
  '.t...t...t...t.',
  '..d...d.d...d..',
  'T..d...*...d..T',
  '..d...d.d...d..',
  '.t...t...t...t.',
  '....D.....D....',
  'd..D...d...D..d',
  '..D...d.d...D..',
  '.D...t...t...D.',
  'T..d...T...d..T',
];

// Эрудит: the standard layout but a non-doubling centre ('+').
const eruditBoard = [
  'T..d...T...d..T',
  '.D...t...t...D.',
  '..D...d.d...D..',
  'd..D...d...D..d',
  '....D.....D....',
  '.t...t...t...t.',
  '..d...d.d...d..',
  'T..d...+...d..T',
  '..d...d.d...d..',
  '.t...t...t...t.',
  '....D.....D....',
  'd..D...d...D..d',
  '..D...d.d...D..',
  '.D...t...t...D.',
  'T..d...T...d..T',
];

function template(variant: Variant): string[] {
  return variant === 'erudit_ru' ? eruditBoard : standardBoard;
}

function premiumOf(ch: string): Premium {
  switch (ch) {
    case 'T':
      return 'TW';
    case 'D':
    case '*':
      return 'DW';
    case 't':
      return 'TL';
    case 'd':
      return 'DL';
    default:
      return '';
  }
}

/** premiumGrid returns the 15x15 premium layout for a variant (row-major). */
export function premiumGrid(variant: Variant): Premium[][] {
  return template(variant).map((line) => Array.from(line, premiumOf));
}

/** centre returns the first-move anchor square (row, col). */
export function centre(variant: Variant): { row: number; col: number } {
  const lines = template(variant);
  for (let r = 0; r < lines.length; r++) {
    const c = lines[r].search(/[*+]/);
    if (c >= 0) return { row: r, col: c };
  }
  return { row: 7, col: 7 };
}

/** RACK_SIZE is the number of tiles drawn to a full rack — 7 for every variant. It sizes
 *  the all-tiles (bingo) bonus test in the local move preview. */
export const RACK_SIZE = 7;

/** BINGO is the all-tiles bonus per variant, ported from scrabble-solver/rules/rules.go:
 *  50 for the Scrabble variants, 15 for Эрудит. The local move preview adds it when a play
 *  uses the whole rack. The dict conformance test pins these to the engine's rulesets. */
export const BINGO: Record<Variant, number> = {
  scrabble_en: 50,
  scrabble_ru: 50,
  erudit_ru: 15,
};

// Tile values and the per-variant alphabet arrive from the server (lib/alphabet.ts); the
// board geometry, centre, rack size and bingo above are the static per-variant constants
// this module owns (all ported from scrabble-solver/rules/rules.go).
