package com.tayo.samples.guesstimator.dao;

import java.time.Instant;
import java.util.Collection;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

import javax.inject.Inject;
import javax.inject.Singleton;

import com.tayo.samples.guesstimator.dto.Game;
import com.tayo.samples.guesstimator.dto.Game.GameGuess;
import com.tayo.samples.guesstimator.dto.Game.GameStatus;
import com.tayo.samples.guesstimator.dto.Game.GuessOperator;
import com.tayo.samples.guesstimator.feed.LeaderBoardBroadcaster;
import com.tayo.samples.guesstimator.dto.GameAnswerRequest;
import com.tayo.samples.guesstimator.dto.GameGuessRequest;
import com.tayo.samples.guesstimator.dto.GameStartRequest;
import com.tayo.samples.guesstimator.util.GameUtils;

/*
 * Handle core game functionality
 * 
 */

@Singleton
public class GameControllerImpl implements GameController {
	
	private static final String NEW_LEADER_UPDATE = "NEW_LEADER_BY_GUESSES";
	
	@Inject
	private LeaderBoardBroadcaster broadcaster;

	private long answerLowerLimit = 1;
	private long answerUpperLimit = 100;

	private Map<String, Game> games = new ConcurrentHashMap<>();
	private Queue<Game> leaderBoard = new PriorityQueue<>();

	@Override
	public Game startNewGame(GameStartRequest gameStartReq) {
		Game game = new Game();
		if (gameStartReq.getPlayerId() != null && !gameStartReq.getPlayerId().trim().equals("")) {
			game.setGameId(UUID.randomUUID().toString());
			game.setGamePlayer(gameStartReq.getPlayerId());
			long answer = GameUtils.generateAnswer(answerLowerLimit, answerUpperLimit);
			Logger.getAnonymousLogger().info("The answer for game " + game.getGameId() + ": " + answer);
			game.setAnswer(answer);
		} else {
			throw new IllegalArgumentException("We can't start a new game with an unnamed player");
		}
		games.put(game.getGameId(), game);
		return game;
	}

	@Override
	public Game checkGuess(GameGuessRequest dto) {
		GameGuess guess = null;
		Game game = games.get(dto.getGameId());
		System.out.println("About to guess");
		if (game != null) {
			guess = game.new GameGuess();
			boolean result = GameUtils.checkGuess(dto, game);
			guess.setGuessValue(dto.getGuessValue());
			guess.setOp(GuessOperator.findValue(dto.getGuessOperator()));
			guess.setGuessResult(result);
			game.getGuesses().add(guess);
		}
		return game;
	}

	@Override
	public Game endGame(GameAnswerRequest dto) {
		Game game = games.get(dto.getGameId());
		try {
		if (game != null) {
			game.setEnded(Instant.now());
			if (game.getAnswer() == dto.getPlayerAnswer()) {
				leaderBoard.add(game);
				game.setGameStatus(GameStatus.CORRECTLY_ANSWERED);
			} else {
				game.setGameStatus(GameStatus.INCORRECTLY_ANSWERED);
			}
			
			if (leaderBoard.peek() != null && leaderBoard.peek().equals(game)) {
				Logger.getAnonymousLogger().info("We have a new leader");
				leaderboardUpdate(game,NEW_LEADER_UPDATE);
			}
		}
		}catch(Exception ex) {
			ex.printStackTrace();
		}

		return game;
	}

	@Override
	public Collection<Game> getLeaderBoard() {
		// TODO Auto-generated method stub
		return this.getLeaderBoard();
	}

	public void leaderboardUpdate(Game game, String eventType) {
		broadcaster.broadcast(game, eventType);
	}

}

@@ -245,24 +245,76 @@
 ntHashMap;%0D%0A
+import java.util.concurrent.PriorityBlockingQueue;%0D%0A
 import java.
@@ -1378,24 +1378,32 @@
 new Priority
+Blocking
 Queue%3C%3E();%0D%0A

Update GameControllerImpl.java