gt: 				Minion minion = minions.get(i);
context: package net.demilich.metastone.gui.playmode;
  
  import java.io.IOException;
  import java.util.HashMap;
  import java.util.List;
  
  import javafx.event.ActionEvent;
  import javafx.event.EventHandler;
  import javafx.fxml.FXML;
  import javafx.fxml.FXMLLoader;
  import javafx.scene.control.Button;
  import javafx.scene.control.Label;
  import javafx.scene.image.ImageView;
  import javafx.scene.input.MouseEvent;
  import javafx.scene.layout.BorderPane;
  import javafx.scene.layout.HBox;
  import javafx.scene.layout.VBox;
  import net.demilich.metastone.game.GameContext;
  import net.demilich.metastone.game.Player;
  import net.demilich.metastone.game.actions.ActionType;
  import net.demilich.metastone.game.actions.GameAction;
  import net.demilich.metastone.game.behaviour.human.HumanTargetOptions;
  import net.demilich.metastone.game.cards.CardCollection;
  import net.demilich.metastone.game.entities.Actor;
  import net.demilich.metastone.game.entities.Entity;
  import net.demilich.metastone.game.entities.minions.Minion;
  import net.demilich.metastone.game.logic.GameLogic;
  import net.demilich.metastone.gui.IconFactory;
  import net.demilich.metastone.gui.cards.HandCard;
  import net.demilich.metastone.gui.playmode.animation.EventVisualizerDispatcher;
  
  public class GameBoardView extends BorderPane {
  
  	@FXML
  	private HBox p1CardPane;
  	@FXML
  	private HBox p2CardPane;
  
  	@FXML
  	private HBox p1MinionPane;
  	@FXML
  	private HBox p2MinionPane;
  
  	@FXML
  	private VBox p1HeroAnchor;
  	@FXML
  	private VBox p2HeroAnchor;
  
  	@FXML
  	private HBox centerMessageArea;
  
  	private HeroToken p1Hero;
  	private HeroToken p2Hero;
  	private HandCard[] p1Cards = new HandCard[GameLogic.MAX_HAND_CARDS];
  	private HandCard[] p2Cards = new HandCard[GameLogic.MAX_HAND_CARDS];
  	private MinionToken[] p1Minions = new MinionToken[GameLogic.MAX_MINIONS];
  	private MinionToken[] p2Minions = new MinionToken[GameLogic.MAX_MINIONS];
  
  	private final HashMap<GameToken, Button> summonHelperMap1 = new HashMap<GameToken, Button>();
  	private final HashMap<GameToken, Button> summonHelperMap2 = new HashMap<GameToken, Button>();
  	private final HashMap<Actor, GameToken> entityTokenMap = new HashMap<Actor, GameToken>();
  
  	private final EventVisualizerDispatcher gameEventVisualizer = new EventVisualizerDispatcher();
  
  	@FXML
  	private Label centerMessageLabel;
  
  	public GameBoardView() {
  		FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/GameBoardView.fxml"));
  		fxmlLoader.setRoot(this);
  		fxmlLoader.setController(this);
  
  		try {
  			fxmlLoader.load();
  		} catch (IOException exception) {
  			throw new RuntimeException(exception);
  		}
  
  		// initialize card ui elements
  		for (int i = 0; i < p1Cards.length; i++) {
  			p1Cards[i] = new HandCard();
  			p1Cards[i].setVisible(false);
  			p2Cards[i] = new HandCard();
  			p2Cards[i].setVisible(false);
  		}
  		p1CardPane.getChildren().addAll(p1Cards);
  		p2CardPane.getChildren().addAll(p2Cards);
  
  		// initialize minion tokens elements
  		for (int i = 0; i < p1Minions.length; i++) {
  			Button summonHelper = createSummonHelper();
  			p1MinionPane.getChildren().add(summonHelper);
  			p1Minions[i] = new MinionToken();
  			p1MinionPane.getChildren().add(p1Minions[i]);
  			summonHelperMap1.put(p1Minions[i], summonHelper);
  
  			summonHelper = createSummonHelper();
  			p2MinionPane.getChildren().add(summonHelper);
  			p2Minions[i] = new MinionToken();
  			p2MinionPane.getChildren().add(p2Minions[i]);
  			summonHelperMap2.put(p2Minions[i], summonHelper);
  		}
  		// create one additional summon helper (for each player)
  		Button summonHelper = createSummonHelper();
  		p1MinionPane.getChildren().add(summonHelper);
  		summonHelperMap1.put(null, summonHelper);
  
  		summonHelper = createSummonHelper();
  		p2MinionPane.getChildren().add(summonHelper);
  		summonHelperMap2.put(null, summonHelper);
  
  		p1Hero = new HeroToken();
  		p2Hero = new HeroToken();
  
  		p1HeroAnchor.getChildren().add(p1Hero);
  		p2HeroAnchor.getChildren().add(p2Hero);
  	}
  
  	private void checkForWinner(GameContext context) {
  		if (context.gameDecided()) {
  			if (context.getWinningPlayerId() == -1) {
  				centerMessageLabel.setStyle("-fx-text-fill: red;");
  				setCenterMessage("Game has ended in a draw.");
  			} else {
  				centerMessageLabel.setStyle("-fx-text-fill: green;");
  				Player winner = context.getPlayer(context.getWinningPlayerId());
  				setCenterMessage("Player " + winner.getName() + " has won the game.");
  			}
  		}
  
  	}
  
  	private Button createSummonHelper() {
  		ImageView icon = new ImageView(IconFactory.getSummonHelper());
  		icon.setFitWidth(32);
  		icon.setFitHeight(32);
  		Button helper = new Button("", icon);
  		helper.setStyle("-fx-padding: 2 2 2 2;");
  		helper.setVisible(false);
  		helper.setManaged(false);
  		return helper;
  	}
  
  	public void disableTargetSelection() {
  		for (GameToken token : entityTokenMap.values()) {
  			token.hideTargetMarker();
  		}
  		for (Button summonHelper : summonHelperMap1.values()) {
  			summonHelper.setVisible(false);
  			summonHelper.setManaged(false);
  		}
  		for (Button summonHelper : summonHelperMap2.values()) {
  			summonHelper.setVisible(false);
  			summonHelper.setManaged(false);
  		}
  		hideCenterMessage();
  	}
  
  	private void enableSpellTargets(final HumanTargetOptions targetOptions) {
  		GameContext context = targetOptions.getContext();
  
  		for (final GameAction action : targetOptions.getActionGroup().getActionsInGroup()) {
  			Entity target = context.resolveSingleTarget(action.getTargetKey());
  			GameToken token = getToken(target);
  
  			EventHandler<MouseEvent> clickedHander = new EventHandler<MouseEvent>() {
  
  				@Override
  				public void handle(MouseEvent event) {
  					disableTargetSelection();
  					targetOptions.getActionSelectionListener().onActionSelected(action);
  				}
  			};
  
  			token.showTargetMarker(clickedHander);
  		}
  	}
  
  	private void enableSummonTargets(final HumanTargetOptions targetOptions) {
  		int playerId = targetOptions.getPlayerId();
  		GameContext context = targetOptions.getContext();
  		for (final GameAction action : targetOptions.getActionGroup().getActionsInGroup()) {
  			Entity target = context.resolveSingleTarget(action.getTargetKey());
  			GameToken token = getToken(target);
  			Button summonHelper = playerId == 0 ? summonHelperMap1.get(token) : summonHelperMap2.get(token);
  			summonHelper.setVisible(true);
  			summonHelper.setManaged(true);
  			EventHandler<ActionEvent> clickedHander = new EventHandler<ActionEvent>() {
  
  				@Override
  				public void handle(ActionEvent event) {
  					disableTargetSelection();
  					targetOptions.getActionSelectionListener().onActionSelected(action);
  				}
  			};
  			summonHelper.setOnAction(clickedHander);
  		}
  	}
  
  	public void enableTargetSelection(final HumanTargetOptions targetOptions) {
  		GameAction action = targetOptions.getActionGroup().getPrototype();
  		if (action.getActionType() == ActionType.SUMMON) {
  			enableSummonTargets(targetOptions);
  		} else {
  			enableSpellTargets(targetOptions);
  		}
  		setCenterMessage("Select target for " + action.getPromptText() + " - ESC to cancel");
  	}
  
  	public GameToken getToken(Entity entity) {
  		return entityTokenMap.get(entity);
  	}
  
  	private void hideCenterMessage() {
  		centerMessageLabel.setVisible(false);
  	}
  
  	private void setCenterMessage(String message) {
  		centerMessageLabel.setText(message);
  		centerMessageLabel.setVisible(true);
  	}
  
  	public void showAnimations(GameContext context) {
  		gameEventVisualizer.visualize((GameContextVisualizable) context, this);
  	}
  
  	public void updateGameState(GameContext context) {
  		entityTokenMap.clear();
  		p1Hero.setHero(context.getPlayer1());
  		p1Hero.highlight(context.getActivePlayer() == context.getPlayer1());
  		entityTokenMap.put(context.getPlayer1().getHero(), p1Hero);
  		p2Hero.setHero(context.getPlayer2());
  		p2Hero.highlight(context.getActivePlayer() == context.getPlayer2());
  		entityTokenMap.put(context.getPlayer2().getHero(), p2Hero);
  
  		updateHandCards(context, context.getPlayer1(), p1Cards);
  		updateHandCards(context, context.getPlayer2(), p2Cards);
  
  		updateMinionTokens(context.getPlayer1(), p1Minions);
  		updateMinionTokens(context.getPlayer2(), p2Minions);
  
  		checkForWinner(context);
  	}
  
  	private void updateHandCards(GameContext context, Player player, HandCard[] handCards) {
  		CardCollection hand = player.getHand();
  		for (int i = 0; i < handCards.length; i++) {
  			if (i < hand.getCount()) {
  				handCards[i].setManaged(true);
  				handCards[i].setVisible(true);
  				handCards[i].setCard(context, hand.get(i), player);
  
  			} else {
  				handCards[i].setManaged(false);
  				handCards[i].setVisible(false);
  			}
  		}
  	}
  
  	private void updateMinionTokens(Player player, MinionToken[] minionTokens) {
  		List<Minion> minions = player.getMinions();
  		for (int i = 0; i < minionTokens.length; i++) {
  			if (i < minions.size()) {
  