import 'dart:math' as math;
import 'dart:ui';

import '../../game/models/grid.dart';
import '../../game/models/piece.dart';

/// Pure mapping between board-local pixels and grid cells.
class BoardGeometry {
  const BoardGeometry({required this.boardSize});

  final double boardSize;

  double get cellSize => boardSize / GridState.size;

  Rect cellRect(int x, int y) =>
      Rect.fromLTWH(x * cellSize, y * cellSize, cellSize, cellSize);

  /// Cell under a local point, or null outside the board.
  (int, int)? cellAt(Offset local) {
    if (local.dx < 0 || local.dy < 0) return null;
    if (local.dx >= boardSize || local.dy >= boardSize) return null;
    return (local.dx ~/ cellSize, local.dy ~/ cellSize);
  }

  /// Nearest anchor for a piece whose visual top-left sits at [pieceTopLeft],
  /// clamped so the piece's bounding box stays on the board.
  (int, int) snapAnchor(Piece piece, Offset pieceTopLeft) {
    var maxDx = 0;
    var maxDy = 0;
    for (final (dx, dy) in piece.offsets) {
      maxDx = math.max(maxDx, dx);
      maxDy = math.max(maxDy, dy);
    }
    final x = (pieceTopLeft.dx / cellSize).round();
    final y = (pieceTopLeft.dy / cellSize).round();
    return (
      x.clamp(0, GridState.size - 1 - maxDx),
      y.clamp(0, GridState.size - 1 - maxDy),
    );
  }
}
