package org.scotlandyard.impl.engine;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.scotlandyard.engine.Game;
import org.scotlandyard.engine.GameException;
import org.scotlandyard.engine.Lobby;
import org.scotlandyard.engine.User;
import org.scotlandyard.engine.boardmap.BoardMap;
import org.scotlandyard.engine.chat.Chat;
import org.scotlandyard.engine.constants.GameStatus;
import org.scotlandyard.impl.engine.boardmap.BoardMapImpl;
/**
* This is the start point of the game engine where the information about the
* lobby available games is found.
* <p>
* to make sure the engine has only one instance to be used
* throughout the life cycle of the game, a singleton instance can be called.
* shared resources are made available such as, chat and lobby.
* </p>
*
* @author Hussain Al-Mutawa
* @version 1.0
* @since Sun Sep 18, 2011
*/
public final class GameEngine {
/**
* specifies the maximum number of detectives per game
*/
public static final int MIXIMUM_NUMBER_OF_DETECTIVES = 5;
/**
* TODO add documentation here
*/
private transient final Lobby lobby;
/**
* TODO add documentation here
*/
private transient final Map<String,BoardMap> boardMaps;
/**
* TODO add documentation here
*/
private transient final Map<String,User> users;
/**
* TODO add documentation here
*/
private static GameEngine engine;
/**
* TODO add documentation here
*/
private transient final Set<Chat>chatHistory;
/**
* gets a singleton instance of the game engine
*
* @return game engine object
*/
public static GameEngine instance(){
if(engine==null)
{
engine=new GameEngine();
}
return GameEngine.engine;
}
/**
* Initialises the game engine a prepares the lobby
*/
private GameEngine(){
super();
boardMaps = new HashMap<String,BoardMap>();
lobby = new LobbyImpl();
chatHistory = new HashSet<Chat>();
users = new HashMap<String, User>();
}
/**
* TODO add documentation here
*
* @param name
* @param email
* @throws GameException
*/
public void loginUser(final String name,final String email) throws GameException{
loginUser(new UserImpl(name, email));
}
/**
* TODO add documentation here
*
* @param user
* @throws GameException
*/
public void loginUser(final User user) throws GameException{
if(user==null){
throw new GameException("can not add user who is null");
}
if(this.getUser(user.getEmail())!=null){
throw new GameException("this user is already added to the list");
}
this.users.put(user.getEmail(), user);
}
/**
* TODO add documentation here
*
* @param email
* @return
*/
public User getUser(final String email){
User users = null;
for(final User user : this.users.values()){
if(user.getEmail().equals(email)){
users = user;
}
}
return users;
}
/**
* performs the following actions:
* <ul><li>clears all games</li>
* <li>clears all users</li>
* <li>clears all board maps</li></ul>
*/
public void clearRecords(){
GameEngine.instance().getLobby().removeAllGames();
GameEngine.instance().getUsers().clear();
GameEngine.instance().getBoardMaps().clear();
}
/**
* TODO add documentation here
*
* @param game
* @return
* @throws GameException
*/
public String startGame(final Game game) throws GameException{
if(game==null){
throw new GameException("Game can not be found");
}
if(game.getMrX()==null){
throw new GameException("Game must have MrX to start");
}
if(game.getDetectives().size()==0){
throw new GameException("Game must have at least one detective");
}
game.setGameStatus(GameStatus.STARTED);
return "done";
}
public BoardMap getNewBoardMap(final String name) throws GameException{
return BoardMapImpl.getNewInstance(name);
}
public Game getNewGame(final String identifier,final User creator,final BoardMap boardMap) throws GameException{
return GameImpl.getNewInstance(identifier, creator, boardMap);
}
/**
* gets the available board maps
*
* @return
*/
public Map<String,BoardMap>getBoardMaps(){
return boardMaps;
}
/**
* TODO add documentation here
*
* @return
*/
public Map<String, User> getUsers() {
return users;
}
/**
* TODO add documentation here
*
* @param email
* @return
*/
public boolean logoutUser(final String email){
boolean found=false;
for(Entry<String,User>entry:users.entrySet()){
if(entry.getValue().getEmail().equals(email)){
this.users.remove(entry.getKey());
found = true;
break;
}
}
if(found){
for(Game game:this.getLobby().getAvailableGames()){
try {
found=game.removePlayer(email);
} catch (GameException e) {
found=false;
}
}
}
return found;
}
/**
* TODO add documentation here
*
* @return
*/
public Set<Chat> getChatHistory() {
return chatHistory;
}
/**
* gets the lobby associated with the game engine
*
* @return lobby object
*/
public Lobby getLobby(){
return lobby;
}
}