@Override
	public void process(HttpServletRequest request,
			HttpServletResponse response, String mobileHash, String message)
			throws Exception {

		EntityManager manager = EMF.get().createEntityManager();
		try {
			Game game = manager.find(Game.class,
					Long.parseLong(request.getParameter("gameId")));
			if ((!mobileHash.equals(game.getWhite()))
					&& (!mobileHash.equals(game.getBlack()))) {
				throw new Exception("You are not part of this Game");
			}
			Operation operation = getOperation(message);
			String opponent = game.getWhite().equals(mobileHash) ? game
					.getBlack() : game.getWhite();
			switch (operation) {
			case MOVE: {
				if (TxtChessUtil.isAI_Game(game)) {
					performAI_Move(manager, request, mobileHash, game, message);
				} else if (game.getDrawRequestedBy() == null
						|| mobileHash.equals(game.getDrawRequestedBy())) {
					performMove(manager,request, mobileHash, game, message);
				} else {
					setJspPath("/showGame");
				}
				break;
			}
			case DRAW: {
				if (TxtChessUtil.isAI_Game(game)) {
					request.setAttribute("___message", opponent
							+ " rejected your draw offer");
					setJspPath("/showGame");
				} else if (game.getDrawRequestedBy() == null
						|| game.getDrawRequestedBy().equals(mobileHash)) {
					game.setDrawRequestedBy(mobileHash);
					EntityTransaction transaction = manager.getTransaction();
					try {
						transaction.begin();
						manager.merge(game);
						transaction.commit();
					} catch (Exception e) {
						try {
							transaction.rollback();
						} catch (Exception ex) {
							ex.printStackTrace();
						}
						throw new Exception(
								"Unable to perform your draw request (Internal Error)",e);
					}
					TxtWebApiUtil
							.pushMessage(
									opponent,
									TxtChessUtil
											.createMoveNotificationMessage(
													"Your Opponent Offered you a Draw",
													TxtChessUtil.getTxtChess(
															game.reCreateBoard(),
															manager.find(
																	ChessUser.class,
																	opponent)),
													"<a href='/moveServlet?gameId="
															+ game.getId()
															+ "&txtweb-message=draw'>Accept Draw offer</a><br/><a href='/moveServlet?gameId="
															+ game.getId()
															+ "&txtweb-message=cancel'>Reject Draw offer</a><br/><a href='/moveServlet?gameId="
															+ game.getId()
															+ "&txtweb-message=resign'>Resign or Abort</a>"));
					request.setAttribute("___message",
							"Your Opponent notified of Draw offer");
					setJspPath("/showGame");
				} else {
					gamesEnded(manager, request, game, Result.DRAW_AGREED,
							mobileHash);
				}

				break;
			}
			case DRAW_CANCEL: {
				game.setDrawRequestedBy(null);
				EntityTransaction transaction = manager.getTransaction();
				try {
					transaction.begin();
					manager.merge(game);
					transaction.commit();
				} catch (Exception e) {
					try {
						transaction.rollback();
					} catch (Exception ex) {
						ex.printStackTrace();
					}
					throw new Exception(
							"Unable to perform your draw cancel request (Internal Error)",e);
				}
				if (!TxtChessUtil.isAI_Game(game)) {
					TxtWebApiUtil
							.pushMessage(
									opponent,
									TxtChessUtil
											.createMoveNotificationMessage(
													"Your Opponent Rejected Your Draw Offer",
													TxtChessUtil.getTxtChess(
															game.reCreateBoard(),
															manager.find(
																	ChessUser.class,
																	opponent)),
													"<a href='/moveServlet?gameId="
															+ game.getId()
															+ "&txtweb-message=draw'>Accept / Offer Draw</a><br/><a href='/moveServlet?gameId="
															+ game.getId()
															+ "&txtweb-message=resign'>Resign or Abort</a>"));
				}
				request.setAttribute("___message",
						"You have rejected your opponent draw offer");
				setJspPath("/showGame");
				break;
			}
			case RESIGN: {
				gamesEnded(manager, request, game, (mobileHash.equals(game
						.getWhite()) ? Result.BLACK_WINS_BY_RESIGNATION
						: Result.WHITE_WINS_BY_RESIGNATION), mobileHash);
				break;
			}
			}
		} finally {
			manager.close();
		}
	}