/* (non-Javadoc)
   * @see org.promasi.playmode.multiplayer.IClientState#onReceive(org.promasi.playmode.multiplayer.ProMaSiClient, java.lang.String)
   */
  @Override
  public void onReceive(ProMaSiClient client, String recData) {
    try {
      Object object = new XMLDecoder(new ByteArrayInputStream(recData.getBytes())).readObject();
      if (object instanceof GameStartedResponse) {

      } else if (object instanceof MessageRequest) {
        MessageRequest request = (MessageRequest) object;
        if (request.getMessage() == null) {
          client.sendMessage(new WrongProtocolResponse().serialize());
          client.disconnect();
        } else {
          _game.sendMessage(_clientId, request.getMessage());
        }
      } else if (object instanceof GameCanceledResponse) {
        changeClientState(client, new ChooseGameClientState(_server, _clientId));
      } else if (object instanceof LeaveGameRequest) {
        _server.leaveGame(_gameId, _clientId);
        changeClientState(client, new ChooseGameClientState(_server, _clientId));
      } else {
        client.sendMessage(new WrongProtocolResponse().serialize());
      }
    } catch (NullArgumentException e) {
      client.sendMessage(new InternalErrorResponse().serialize());
      client.disconnect();
    } catch (IllegalArgumentException e) {
      client.sendMessage(new InternalErrorResponse().serialize());
      client.disconnect();
    }
  }
  /**
   * @param clientId
   * @param game
   * @throws NullArgumentException
   */
  public WaitingGameClientState(
      String clientId,
      ProMaSiServer server,
      ProMaSiClient client,
      String gameId,
      MultiPlayerGame game)
      throws NullArgumentException {
    if (game == null) {
      throw new NullArgumentException("Wrong argument game==null");
    }

    if (clientId == null) {
      throw new NullArgumentException("Wrong argument clientId==null");
    }

    if (client == null) {
      throw new NullArgumentException("Wrong argument cleint==null");
    }

    if (server == null) {
      throw new NullArgumentException("Wrong argument server==null");
    }

    if (gameId == null) {
      throw new NullArgumentException("Wrong argument gameId==null");
    }

    _gameId = gameId;
    _server = server;
    _client = client;
    _game = game;
    _game.addListener(this);
    _clientId = clientId;
  }
 @Override
 public void onConnectionError(ProMaSiClient client) {
   try {
     _game.leaveGame(_clientId);
   } catch (NullArgumentException e) {
     // Logger
   }
 }
  @Override
  public void gameStarted(
      String playerId, IMultiPlayerGame game, SerializableGameModel gameModel, DateTime dateTime) {
    if (playerId.equals(_clientId)) {
      try {
        _game.removeListener(this);
        changeClientState(_client, new PlayingGameClientState(_server, _client, _clientId, _game));
      } catch (NullArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

      gameModel.setProjects(null);
      _client.sendMessage(new GameStartedRequest(gameModel, dateTime.toString()).serialize());
    }
  }
  /**
   * Accepted requests are: {@link JoinGameRequest}, {@link CreateGameRequest}, {@link
   * UpdateAvailableGameListRequest}, In case of any other type of request client will be
   * disconnected.
   */
  @Override
  public void onReceive(ProMaSiClient client, String recData) {
    try {
      Object object = new XMLDecoder(new ByteArrayInputStream(recData.getBytes())).readObject();
      if (object instanceof JoinGameRequest) {
        try {
          _logger.info("Received message :'" + JoinGameRequest.class.toString() + "'");
          JoinGameRequest request = (JoinGameRequest) object;
          MultiPlayerGame game;
          game = _server.joinGame(_clientId, request.getGameId());

          JoinGameResponse response =
              new JoinGameResponse(
                  game.getGameName(), game.getGameDescription(), game.getGamePlayers());
          client.removeListener(this);
          client.addListener(
              new WaitingGameClientState(_clientId, _server, client, request.getGameId(), game));
          client.sendMessage(response);
        } catch (IllegalArgumentException e) {
          client.sendMessage(new JoinGameFailedResponse());
        }

      } else if (object instanceof CreateGameRequest) {
        _logger.info("Received message :'" + CreateGameRequest.class.toString() + "'");
        CreateGameRequest request = (CreateGameRequest) object;
        GameModelMemento gameModel = request.getGameModel();
        if (gameModel == null) {
          _logger.warn("Invalid message detected gameModel == null, client will be disconnected");
          client.sendMessage(new WrongProtocolResponse());
          client.disconnect();
          return;
        }

        MarketPlaceMemento marketPlace = gameModel.getMarketPlace();
        if (marketPlace == null) {
          _logger.warn("Invalid message detected marketPlace == null, client will be disconnected");
          client.sendMessage(new WrongProtocolResponse());
          client.disconnect();
        }

        CompanyMemento company = gameModel.getCompany();
        if (company == null) {
          _logger.warn("Invalid message detected company == null, client will be disconnected");
          client.sendMessage(new WrongProtocolResponse());
          client.disconnect();
        }

        Queue<ProjectMemento> sProjects = gameModel.getProjects();
        if (sProjects == null) {
          _logger.warn("Invalid message detected projects == null, client will be disconnected");
          client.sendMessage(new WrongProtocolResponse());
          client.disconnect();
        }

        Queue<Project> projects = new LinkedList<Project>();
        for (ProjectMemento currentProject : sProjects) {
          projects.add(currentProject.getProject());
        }

        MultiPlayerGame game =
            new MultiPlayerGame(
                _clientId,
                request.getGameId(),
                gameModel.getGameDescription(),
                marketPlace.getMarketPlace(),
                company.getCompany(),
                projects);

        if (_server.createGame(request.getGameId(), game)) {
          CreateGameResponse response =
              new CreateGameResponse(
                  request.getGameId(), gameModel.getGameDescription(), game.getGamePlayers());
          client.sendMessage(response);
          client.removeListener(this);
          client.addListener(
              new WaitingPlayersClientState(_clientId, request.getGameId(), client, game, _server));
        } else {
          _logger.warn("Create game failed");
        }
      } else if (object instanceof UpdateAvailableGameListRequest) {
        _logger.info("Received message :'" + UpdateAvailableGameListRequest.class.toString() + "'");
        UpdateGameListRequest request = new UpdateGameListRequest(_server.getAvailableGames());
        client.sendMessage(request);
      } else {
        _logger.warn("Received an invalid message type '" + object.toString() + "'");
        client.sendMessage(new WrongProtocolResponse());
        client.disconnect();
      }
    } catch (Exception e) {
      _logger.warn("Internal error client will be disconnected");
      client.sendMessage(new InternalErrorResponse());
      client.disconnect();
    }
  }