import { Injectable, DestroyRef, inject } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { GameApiService } from './game-api.service'; import { getPieceAtSquare, isPieceColor } from '../core/chess/fen.utils'; import { GameState, LegalMove } from '../models/game.models'; export interface BoardSelection { selectedSquare: string | null; highlightedSquares: string[]; selectedSquareMoves: LegalMove[]; } @Injectable({ providedIn: 'root' }) export class BoardSelectionService { private readonly gameApi = inject(GameApiService); private readonly destroyRef = inject(DestroyRef); handleSquareSelection( square: string, gameId: string, state: GameState | null, currentSelection: BoardSelection, onMovesLoaded: (moves: LegalMove[]) => void, onError: (error: string) => void ): BoardSelection { if (!state) { return currentSelection; } // If clicking on a highlighted square, it's a move if (currentSelection.selectedSquare && currentSelection.highlightedSquares.includes(square)) { const selectedMove = currentSelection.selectedSquareMoves.find((move) => move.to === square); if (selectedMove) { return { selectedSquare: null, highlightedSquares: [], selectedSquareMoves: [] }; } return currentSelection; } // Check if square has a piece of the correct color const piece = getPieceAtSquare(state.fen, square); if (!piece || !isPieceColor(piece, state.turn)) { return { selectedSquare: null, highlightedSquares: [], selectedSquareMoves: [] }; } // Load legal moves for this square this.gameApi .getLegalMoves(gameId, square) .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe({ next: (response) => { onMovesLoaded(response.moves); }, error: () => { onError('Could not load legal moves for selected square.'); } }); return { selectedSquare: square, highlightedSquares: [], selectedSquareMoves: [] }; } clearSelection(): BoardSelection { return { selectedSquare: null, highlightedSquares: [], selectedSquareMoves: [] }; } }