/**
 * @file knight-king-pattern.js
 * @description Pattern for implementing non-sliding pieces (Knight, King)
 * These pieces jump to specific positions
 */

import Piece from '../models/Piece.js';
import { DIRECTIONS } from '../utils/Constants.js';
import { isValidPosition } from '../utils/Helpers.js';

/**
 * @class Knight
 * @extends Piece
 * @description Knight implementation using jump pattern
 *
 * Knight moves in L-shape: 2 squares in one direction, 1 square perpendicular
 * Can jump over other pieces
 */
class Knight extends Piece {
  constructor(color, position) {
    super(color, position, 'knight');
  }

  /**
   * Gets all valid moves for this knight
   *
   * @param {Board} board - Current board state
   * @returns {Array<Object>} Array of valid positions
   */
  getValidMoves(board) {
    const moves = [];
    const { row, col } = this.position;

    // Knight has 8 possible L-shaped moves
    const knightMoves = DIRECTIONS.KNIGHT;

    // Check each possible move
    for (const move of knightMoves) {
      const newPos = {
        row: row + move.row,
        col: col + move.col
      };

      // Check if position is valid (on board)
      if (!isValidPosition(newPos.row, newPos.col)) {
        continue;
      }

      const piece = board.getPieceAt(newPos);

      // Can move to empty square or capture enemy
      if (!piece || piece.color !== this.color) {
        moves.push(newPos);
      }
    }

    return moves;
  }

  clone() {
    const clone = new Knight(this.color, { ...this.position });
    clone.hasMoved = this.hasMoved;
    return clone;
  }
}

/**
 * @class King
 * @extends Piece
 * @description King implementation using adjacent square pattern
 *
 * King moves one square in any direction
 * Special move: Castling (handled separately)
 */
class King extends Piece {
  constructor(color, position) {
    super(color, position, 'king');
  }

  /**
   * Gets all valid moves for this king
   *
   * @param {Board} board - Current board state
   * @returns {Array<Object>} Array of valid positions
   */
  getValidMoves(board) {
    const moves = [];
    const { row, col } = this.position;

    // King can move one square in 8 directions
    const directions = [...DIRECTIONS.ORTHOGONAL, ...DIRECTIONS.DIAGONAL];

    // Check each adjacent square
    for (const direction of directions) {
      const newPos = {
        row: row + direction.row,
        col: col + direction.col
      };

      // Check if position is valid
      if (!isValidPosition(newPos.row, newPos.col)) {
        continue;
      }

      const piece = board.getPieceAt(newPos);

      // Can move to empty square or capture enemy
      if (!piece || piece.color !== this.color) {
        moves.push(newPos);
      }
    }

    // TODO: Add castling moves
    // Only if king hasn't moved
    // Only if rook hasn't moved
    // Only if squares between are empty
    // Only if king is not in check
    // Only if king doesn't pass through check
    // See castling example in special-moves.js

    return moves;
  }

  /**
   * Checks if king can castle kingside
   *
   * @param {Board} board - Current board state
   * @returns {boolean} True if kingside castling is legal
   */
  canCastleKingside(board) {
    // TODO: Implement castling validation
    // This is complex and often handled in RuleEngine
    return false;
  }

  /**
   * Checks if king can castle queenside
   *
   * @param {Board} board - Current board state
   * @returns {boolean} True if queenside castling is legal
   */
  canCastleQueenside(board) {
    // TODO: Implement castling validation
    return false;
  }

  clone() {
    const clone = new King(this.color, { ...this.position });
    clone.hasMoved = this.hasMoved;
    return clone;
  }
}

/**
 * PATTERN SUMMARY - NON-SLIDING PIECES:
 *
 * Unlike sliding pieces, these pieces:
 * 1. Have a fixed set of possible moves (no sliding)
 * 2. Can't be blocked (Knight) or move only 1 square (King)
 * 3. Check each possible position directly
 *
 * Algorithm:
 * 1. Get all possible move offsets
 * 2. For each offset:
 *    a. Calculate new position
 *    b. Validate position is on board
 *    c. Check if square is empty or has enemy
 *    d. Add to moves if valid
 *
 * DIFFERENCE FROM SLIDING:
 * - Sliding: Loop until blocked
 * - Non-sliding: Check each position once
 *
 * KNIGHT SPECIAL:
 * - Only piece that can jump over others
 * - Don't need to check path, only destination
 *
 * KING SPECIAL:
 * - Must not move into check (validated elsewhere)
 * - Castling is complex special move
 * - Usually limited to 8 moves, but critical to protect
 */

export { Knight, King };
