package net.demilich.metastone.gui.playmode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.text.TextAlignment;
import net.demilich.metastone.GameNotification;
import net.demilich.metastone.NotificationProxy;
import net.demilich.metastone.game.GameContext;
import net.demilich.metastone.game.actions.ActionType;
import net.demilich.metastone.game.actions.BattlecryAction;
import net.demilich.metastone.game.actions.DiscoverAction;
import net.demilich.metastone.game.actions.GameAction;
import net.demilich.metastone.game.actions.HeroPowerAction;
import net.demilich.metastone.game.actions.PhysicalAttackAction;
import net.demilich.metastone.game.actions.PlayCardAction;
import net.demilich.metastone.game.behaviour.human.ActionGroup;
import net.demilich.metastone.game.behaviour.human.HumanActionOptions;
import net.demilich.metastone.game.behaviour.human.HumanTargetOptions;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.entities.Entity;
import net.demilich.metastone.game.targeting.TargetSelection;
import net.demilich.metastone.gui.cards.CardTooltip;
public class HumanActionPromptView extends VBox {
private static String getActionString(GameContext context, GameAction action) {
PlayCardAction playCardAction = null;
Card card = null;
String actionString = "";
switch (action.getActionType()) {
case HERO_POWER:
HeroPowerAction heroPowerAction = (HeroPowerAction) action;
card = context.resolveCardReference(heroPowerAction.getCardReference());
actionString = "HERO POWER: " + card.getName();
break;
case BATTLECRY:
BattlecryAction battlecry = (BattlecryAction) action;
actionString = "BATTLECRY " + battlecry.getSpell().getSpellClass().getSimpleName();
break;
case PHYSICAL_ATTACK:
PhysicalAttackAction physicalAttackAction = (PhysicalAttackAction) action;
Entity attacker = context.resolveSingleTarget(physicalAttackAction.getAttackerReference());
actionString = "ATTACK with " + attacker.getName();
break;
case SPELL:
playCardAction = (PlayCardAction) action;
card = context.resolveCardReference(playCardAction.getCardReference());
actionString = "CAST SPELL: " + card.getName();
break;
case SUMMON:
playCardAction = (PlayCardAction) action;
card = context.resolveCardReference(playCardAction.getCardReference());
actionString = "SUMMON: " + card.getName();
break;
case EQUIP_WEAPON:
playCardAction = (PlayCardAction) action;
card = context.resolveCardReference(playCardAction.getCardReference());
actionString = "WEAPON: " + card.getName();
break;
case END_TURN:
actionString = "END TURN";
break;
case DISCOVER:
DiscoverAction discover = (DiscoverAction) action;
actionString = "DISCOVER " + discover.getSpell().getSpellClass().getSimpleName();
break;
default:
return "<unknown action " + action.getActionType() + ">";
}
if (action.getActionSuffix() != null) {
actionString += " (" + action.getActionSuffix() + ")";
}
return actionString;
}
private final List<Node> existingButtons = new ArrayList<Node>();
public HumanActionPromptView() {
Label headerLabel = new Label("Choose action:");
headerLabel.setStyle("-fx-font-family: Arial;-fx-font-weight: bold; -fx-font-size: 16pt;");
setPrefWidth(Region.USE_COMPUTED_SIZE);
setSpacing(2);
setPadding(new Insets(8));
setAlignment(Pos.CENTER);
getChildren().add(headerLabel);
}
private Node createActionButton(final ActionGroup actionGroup, HumanActionOptions options) {
GameContext context = options.getContext();
Button button = new Button(getActionString(context, actionGroup.getPrototype()));
button.setStyle("-fx-font-size: 12px; -fx-padding: 4 8 4 8;");
button.setWrapText(true);
button.setPrefWidth(200);
button.setTextAlignment(TextAlignment.CENTER);
switch (actionGroup.getPrototype().getActionType()) {
case BATTLECRY:
break;
case DISCOVER:
CardTooltip tooltipContent = new CardTooltip();
DiscoverAction discover = (DiscoverAction) actionGroup.getPrototype();
Card card = discover.getCard();
if (card != null) {
tooltipContent.setCard(card);
Tooltip tooltip = new Tooltip();
tooltip.setGraphic(tooltipContent);
Tooltip.install(button, tooltip);
} else {
tooltipContent.setNonCard(discover.getName(), discover.getDescription());
Tooltip tooltip = new Tooltip();
tooltip.setGraphic(tooltipContent);
Tooltip.install(button, tooltip);
}
break;
case END_TURN:
break;
case EQUIP_WEAPON:
break;
case HERO_POWER:
break;
case PHYSICAL_ATTACK:
break;
case SPELL:
break;
case SUMMON:
break;
case SYSTEM:
break;
default:
break;
}
// only one action with no target selection or summon with no other
// minion on board
if (actionGroup.getActionsInGroup().size() == 1 && (actionGroup.getPrototype().getTargetRequirement() == TargetSelection.NONE
|| actionGroup.getPrototype().getActionType() == ActionType.SUMMON)) {
button.setOnAction(event -> {
options.getBehaviour().onActionSelected(actionGroup.getPrototype());
setVisible(false);
});
return button;
}
HumanTargetOptions humanTargetOptions = new HumanTargetOptions(options.getBehaviour(), context, options.getPlayer().getId(),
actionGroup);
button.setOnAction(event -> {
NotificationProxy.sendNotification(GameNotification.HUMAN_PROMPT_FOR_TARGET, humanTargetOptions);
setVisible(false);
});
return button;
}
private Collection<Node> createActionButtons(HumanActionOptions options) {
Collection<Node> buttons = new ArrayList<Node>();
Collection<ActionGroup> actionGrups = groupActions(options);
for (ActionGroup actionGroup : actionGrups) {
buttons.add(createActionButton(actionGroup, options));
}
return buttons;
}
private Collection<ActionGroup> groupActions(HumanActionOptions options) {
Collection<ActionGroup> actionGroups = new ArrayList<>();
for (GameAction action : options.getValidActions()) {
if (!matchesExistingGroup(action, actionGroups)) {
ActionGroup newActionGroup = new ActionGroup(action);
actionGroups.add(newActionGroup);
}
}
return actionGroups;
}
private boolean matchesExistingGroup(GameAction action, Collection<ActionGroup> existingActionGroups) {
for (ActionGroup actionGroup : existingActionGroups) {
if (actionGroup.getPrototype().isSameActionGroup(action)) {
actionGroup.add(action);
return true;
}
}
return false;
}
public void setActions(HumanActionOptions options) {
getChildren().removeAll(existingButtons);
existingButtons.clear();
Collection<Node> buttons = createActionButtons(options);
existingButtons.addAll(buttons);
getChildren().addAll(buttons);
setVisible(true);
}
}