package de.movope.game;

import de.movope.game.piece.Pawn;
import de.movope.game.piece.Piece;

import java.awt.*;
import java.util.Arrays;
import java.util.List;

public class MoveEvaluator {

    ChessBoard board;

    private MoveEvaluator(ChessBoard board) {
        this.board = board;
    }

    public static MoveEvaluator with(ChessBoard board) {
        return new MoveEvaluator(board);
    }

    public MoveEvaluation analyse(String aSquare) {
        Square square = Square.create(aSquare);
        if (!square.onBoard()) {
            return null;
        }
        Piece piece = board.getPieceAt(aSquare);
        if (piece == Piece.NULL) {
            return null;
        }
        return determinePossibleTargetsOnBoard(square, piece);
    }


    private MoveEvaluation determinePossibleTargetsOnBoard(final Square start, final Piece piece) {

        final MoveEvaluation.Builder builder = new MoveEvaluation.Builder();
        builder.startAt(start);

        piece.directions().stream()
                .map(dir -> possibleMoves(dir, start, piece))
                .forEach(result -> result.getMoves().stream().forEach(builder::addMove));

        piece.directions().stream()
                .map(dir -> possibleMoves(dir, start, piece))
                .forEach(result -> result.getAttacks().stream()
                        .filter(attack -> board.occupiedFromEnemy(attack, piece.getColor().invert()))
                        .forEach(builder::addAttack));

        return builder.create();
    }

    private EvaluationResult possibleMoves(Point dir, Square start, Piece piece) {
        if (piece instanceof Pawn) {
            return possibleMoves(dir, start, (Pawn) piece);
        }
        EvaluationResult result = new EvaluationResult();
        Square target = (Square) start.clone();

        for (int i = 0; i < piece.getMaximumMoves(); i++) {
            target = target.move(dir.x, dir.y);
            if (board.canPieceMoveTo(target)) {
                result.addMove(target);
            } else {
                if (target.onBoard()) {
                    result.addPossibleAttack(target);
                }
                break;
            }
        }
        return result;
    }

    private EvaluationResult possibleMoves(Point dir, Square start, Pawn pawn) {
        EvaluationResult result = new EvaluationResult();
        Square target = (Square) start.clone();

        boolean firstMove = ((pawn.getColor() == Color.BLACK && start.getFile() == 6)) ||
                ((pawn.getColor() == Color.WHITE) && start.getFile() == 1);

        int maximumMoves = firstMove ? 2 : 1;

        for (int i = 0; i < maximumMoves; i++) {
            target = target.move(dir.x, dir.y);
            if (board.canPieceMoveTo(target)) {
                result.addMove(target);
            }
        }
        List<Point> attackDirections = Arrays.asList(new Point(-1, dir.y), new Point(1, dir.y));
        attackDirections.stream().map(direction -> ((Square) start.clone()).move(direction.x, direction.y))
                                .filter(Square::onBoard)
                                .forEach(result::addPossibleAttack);

        return result;
    }
}

@@ -721,23 +721,16 @@
 eTargets
-OnBoard
 (square,
@@ -801,15 +801,8 @@
 gets
-OnBoard
 (fin
@@ -994,32 +994,42 @@
                 
+          
 .map(dir -%3E poss
@@ -1066,32 +1066,42 @@
                 
+  
+        
 .forEach(result 
@@ -1129,16 +1129,79 @@
 stream()
+%0A                                                              
 .forEach
@@ -1266,32 +1266,42 @@
                 
+         
+ 
 .map(dir -%3E poss
@@ -1322,32 +1322,42 @@
  start, piece))%0A
+          
                 
@@ -1396,32 +1396,72 @@
 acks().stream()%0A
+                                        
                 
@@ -1546,16 +1546,56 @@
 ert()))%0A
+                                        
         

rename method