package es.mahulo.battleship.service;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import es.mahulo.battleship.api.dao.GameConfigDao;
import es.mahulo.battleship.api.dao.GameDao;
import es.mahulo.battleship.api.dao.PlayerDao;
import es.mahulo.battleship.api.dao.UserDao;
import es.mahulo.battleship.api.service.Config;
import es.mahulo.battleship.api.service.GameService;
import es.mahulo.battleship.model.Cell;
import es.mahulo.battleship.model.Game;
import es.mahulo.battleship.model.GameConfig;
import es.mahulo.battleship.model.GameStatus;
import es.mahulo.battleship.model.Player;
import es.mahulo.battleship.model.Ship;
import es.mahulo.battleship.model.Shot;
import es.mahulo.battleship.model.User;
@Service
public class GameServiceImpl implements GameService {
Logger logger = Logger.getLogger(GameServiceImpl.class.getName());
private Config configService;
private PlayerDao playerDao;
private GameDao gameDao;
private UserDao userDao;
private GameConfigDao gameConfigDao;
@Autowired
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Autowired
public void setGameConfigDao(GameConfigDao gameConfigDao) {
this.gameConfigDao = gameConfigDao;
}
@Autowired
public void setConfigService(Config configService) {
this.configService = configService;
}
@Autowired
public void setPlayerDao(PlayerDao playerDao) {
this.playerDao = playerDao;
}
@Autowired
public void setGameDao(GameDao gameDao) {
this.gameDao = gameDao;
}
public GameServiceImpl() {
}
@Override
@Transactional
public List<Game> getAllFromUser(String userId) {
User user = userDao.findByName(userId);
logger.debug("user found: " + user);
List<Game> games = new ArrayList<Game>();
for (Player player :user.getPlayers() ) {
Game game = player.getGame();
if (game.getStatus()!=GameStatus.Wind1 ||
game.getStatus()!=GameStatus.Wind2 ||
game.getStatus()!=GameStatus.Draw ) {
games.add(game);
}
}
return games;
}
@Override
@Transactional
public Game startUp(String userId) throws Exception {
logger.info("createGame " + userId);
User user = userDao.findByName(userId);
logger.debug("user found: " + user);
Game game = new Game();
GameConfig gameConfig = gameConfigDao.find(1L); //TODO DEFINE A TABLE DEFAULT CONFIGURATION
List<Player> players = new ArrayList<Player>();
Player player = new Player();
player.setUser(user);
player.setShips(new ArrayList<Ship>());
player.setShots(new ArrayList<Shot>());
player.setGame(game);
players.add(player);
game.setGameConfig(gameConfig);
game.setStatus(GameStatus.StartUp);
game.setPlayers(players);
gameDao.create(game);
logger.debug("game save: " + game);
return game;
}
@Override
@Transactional
public Game joinPlayer(Long gameId, String userId) throws Exception {
Game game = gameDao.find(gameId);
if (game.getStatus() == GameStatus.StartUp) {
User user = userDao.findByName(userId);
Player player = new Player();
player.setUser(user);
player.setShips(new ArrayList<Ship>());
player.setShots(new ArrayList<Shot>());
player.setGame(game);
List<Player> players = game.getPlayers();
players.add(player);
game.setStatus(GameStatus.Configuring);
gameDao.update(game);
return game;
} else {
throw new Exception("Wrong State");
}
}
@Override
@Transactional(rollbackFor=Exception.class)
public void addShip(Long gameId, String userId, List<Ship> ships) throws Exception {
logger.info("Add Ship " + userId + " " + ships);
Game game = gameDao.find(gameId);
Player player = foundPlayer(game.getPlayers(),userId);
logger.info("Player found " + player);
if ( game.getStatus() == GameStatus.Configuring ) {
if (configService.isComplete(game.getGameConfig(),player) ) {
logger.info("Configuration complete, not possible to add more ships.");
throw new Exception("Configuration complete, not possible to add more ships.");
}
for (Ship ship : ships) {
configService.isValid (game, player,ship);
player.getShips().add(ship);
ship.setPlayer(player);
for (Cell cell : ship.getCells()) {
cell.setHit(false);
cell.setShip(ship);
}
}
if (!configService.isComplete(game.getGameConfig(),player) ) {
logger.info("Ship configuration incorrect.");
throw new Exception("Ship configuration incorrect.");
}
playerDao.create(player);
List<Player> players = game.getPlayers();
if (players.size() == 2) {
if (configService.isComplete(game.getGameConfig(),players.get(0)) &&
configService.isComplete(game.getGameConfig(),players.get(1))) {
game.setStatus(GameStatus.Round1);
}
}
} else {
logger.info("Wrong State");
throw new Exception("Wrong State");
}
}
@Override
public Boolean shot(Long gameId, String userId, Shot shot) throws Exception {
logger.info("shot " + userId + " " + shot);
Game game = gameDao.find(gameId);
logger.debug("game " + game);
Player player = foundPlayer(game.getPlayers(),userId);
logger.debug("found " + player);
Boolean isHit = false;
switch (game.getStatus()) {
case Round1:
logger.debug("Round 1 ");
if (game.getPlayers().get(1) != null &&
game.getPlayers().get(1).equals(player)) {
isHit = shot(game.getPlayers().get(1),shot);
logger.debug("isHit "+ isHit);
if (isAllShipDestroyed(game.getPlayers().get(1)) ) {
game.setStatus(GameStatus.Wind1);
logger.debug("All Ship Destroyed ");
} else
game.setStatus(GameStatus.Round2);
} else {
throw new Exception("Wrong state");
}
break;
case Round2:
logger.debug("Round 2 ");
if (game.getPlayers().get(0) != null &&
game.getPlayers().get(0).equals(player)) {
isHit = shot(game.getPlayers().get(0),shot);
logger.debug("isHit "+ isHit);
if (isAllShipDestroyed(game.getPlayers().get(0)) ) {
game.setStatus(GameStatus.Wind2);
logger.debug("All Ship Destroyed ");
} else
game.setStatus(GameStatus.Round1);
} else
throw new Exception("Wrong state");
break;
case Wind1:
logger.debug("Wind 1 ");
if (game.getPlayers().get(0) != null &&
game.getPlayers().get(0).equals(player)) {
isHit = shot(game.getPlayers().get(0),shot);
logger.debug("isHit "+ isHit);
if (isAllShipDestroyed(game.getPlayers().get(0)) ) {
game.setStatus(GameStatus.Draw);
logger.debug("All Ship Destroyed ");
} else {
game.setStatus(GameStatus.Wind1);
}
} else
throw new Exception("Wrong state");
break;
default:
throw new Exception("Wrong state");
}
gameDao.update(game);
return isHit;
}
public Boolean shot(Player player,Shot shot) {
for (Ship ship : player.getShips() )
for (Cell cell: ship.getCells() ) {
if (cell.getX()==shot.getX() && cell.getY()==shot.getY()) {
cell.setHit(true);
return true;
}
}
return false;
}
private Player foundPlayer(List<Player> players,String userId) throws Exception {
logger.info("found Player " + players + " " + userId);
Player player = null;
for (Player aPlayer :players) {
if (aPlayer.getUser().getName().equals(userId)) {
player = aPlayer;
break;
}
}
if (player == null) throw new Exception("Player not found");
return player;
}
public Boolean isAllShipDestroyed(Player player) {
for (Ship ship : player.getShips() )
for (Cell cell: ship.getCells() ) {
if (!cell.getHit()) {
return false;
}
}
return true;
}
}