package com.gomoku.controller;

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.summingInt;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.gomoku.domain.game.GameStatus;
import com.gomoku.repository.GameRepository;
import com.gomoku.repository.PlayerRepository;
import com.gomoku.repository.entity.Game;
import com.gomoku.repository.entity.History;
import com.gomoku.repository.entity.Player;
import com.gomoku.repository.entity.Score;
import com.gomoku.service.GameTaskScheduler;

/**
 * Rest controller to handle game actions.
 *
 * @author zeldan
 *
 */
@CrossOrigin
@RequestMapping("/api/games")
@RestController
public class GameController {

    private static final int MINIMUM_PLAYER_NUMBER_TO_START = 2;

    private final GameTaskScheduler gameTaskScheduler;

    private final GameRepository gameRepository;

    private final PlayerRepository playerRepository;

    public GameController(final GameTaskScheduler gameTaskScheduler, final GameRepository gameRepository, final PlayerRepository playerRepository) {
        this.gameTaskScheduler = gameTaskScheduler;
        this.gameRepository = gameRepository;
        this.playerRepository = playerRepository;
    }

    @PostMapping
    public String createGame() {
        return gameRepository.save(new Game()).getId();
    }

    @PostMapping("/{gameId}/start")
    public String start(@PathVariable final String gameId) {
        final List<Player> players = playerRepository.findAll();
        if (players.size() >= MINIMUM_PLAYER_NUMBER_TO_START) {
            final Game game = gameRepository.findOne(gameId);
            game.setGameStatus(GameStatus.IN_PROGRESS);
            game.setPlayers(players.stream().map(Player::getUserName).collect(Collectors.toList()));
            gameRepository.save(game);
            startNewGame(gameId);
            return "IN_PROGRESS";
        } else {
            throw new RuntimeException("Minimum number of players is 2.");
        }
    }

    @GetMapping
    public List<Game> getAllGames() {
        return gameRepository.findAll();
    }

    @GetMapping("/{gameId}")
    public Game getGame(@PathVariable final String gameId) {
        return gameRepository.findOne(gameId);
    }

    @GetMapping("/{gameId}/scores")
    public Map<String, Integer> getScore(@PathVariable final String gameId) {
        final List<Score> scoresByGameId = gameRepository.findOne(gameId).getScores();
        return scoresByGameId.stream().collect(groupingBy(Score::getPlayer, summingInt(Score::getScore)));
    }

    @GetMapping("/{gameId}/histories")
    public List<History> getHistories(@PathVariable final String gameId) {
        return gameRepository.findOne(gameId).getHistories();
    }

    private void startNewGame(final String gameId) {
        new Thread(() -> {
            gameTaskScheduler.startAndScheduleGames(gameId);
        }).start();
    }
}

@@ -182,44 +182,8 @@
 Map;
-%0Aimport java.util.stream.Collectors;
 %0A%0Aim
@@ -412,32 +412,92 @@
 on.PostMapping;%0A
+import org.springframework.web.bind.annotation.RequestBody;%0A
 import org.sprin
@@ -698,55 +698,8 @@
 ry;%0A
-import com.gomoku.repository.PlayerRepository;%0A
 impo
@@ -785,52 +785,8 @@
 ry;%0A
-import com.gomoku.repository.entity.Player;%0A
 impo
@@ -1211,62 +1211,8 @@
 y;%0A%0A
-    private final PlayerRepository playerRepository;%0A%0A
     
@@ -1315,49 +1315,8 @@
 tory
-, final PlayerRepository playerRepository
 ) %7B%0A
@@ -1417,58 +1417,8 @@
 ry;%0A
-        this.playerRepository = playerRepository;%0A
     
@@ -1648,550 +1648,717 @@
 nal 
-List%3CPlayer%3E players = playerRepository.findAll();%0A        if (players.size() %3E= MINIMUM_PLAYER_NUMBER_TO_START) %7B%0A            final Game game = gameRepository.findOne(gameId);%0A            game.setGameStatus(GameStatus.IN_PROGRESS);%0A            game.setPlayers(players.stream().map(Player::getUserName).collect(Collectors.toList()));%0A            gameRepository.save(game);%0A            startNewGame(gameId);%0A            return %22IN_PROGRESS%22;%0A        %7D else %7B%0A            throw new RuntimeException(%22Minimum number of players is 2.%22);%0A        %7D
+Game game = gameRepository.findOne(gameId);%0A        final List%3CString%3E players = game.getPlayers();%0A        if (players.size() %3E= MINIMUM_PLAYER_NUMBER_TO_START) %7B%0A            game.setGameStatus(GameStatus.IN_PROGRESS);%0A            gameRepository.save(game);%0A            startNewGame(gameId);%0A            return %22IN_PROGRESS%22;%0A        %7D else %7B%0A            throw new RuntimeException(%22Minimum number of players is 2.%22);%0A        %7D%0A    %7D%0A%0A    @PostMapping(%22/%7BgameId%7D/players%22)%0A    public void setPlayers(@PathVariable final String gameId, @RequestBody final List%3CString%3E playerIds) %7B%0A        final Game game = gameRepository.findOne(gameId);%0A        game.setPlayers(playerIds);%0A        gameRepository.save(game);
 %0A   

add endpoint to be able to set players via rest