package mage.abilities.costs; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCost; import mage.choices.Choice; import mage.choices.ChoiceImpl; import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; import mage.target.Targets; import mage.util.CardUtil; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; public class OrCost implements Cost { private final List costs = new ArrayList<>(); private String description; // which cost was slected to pay private Cost selectedCost; public OrCost(String description, Cost... costs) { Collections.addAll(this.costs, costs); this.description = description; } protected OrCost(final OrCost cost) { cost.costs.stream().map(Cost::copy).forEach(this.costs::add); this.description = cost.description; this.selectedCost = cost.selectedCost; } @Override public UUID getId() { throw new RuntimeException("Not supported method"); } @Override public OrCost setText(String text) { this.description = text; return this; } @Override public String getText() { return description; } @Override public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { return costs.stream().anyMatch(cost -> cost.canPay(ability, source, controllerId, game)); } @Override public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana) { return pay(ability, game, source, controllerId, noMana, this); } @Override public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { selectedCost = null; List usable = costs .stream() .filter(cost -> cost.canPay(ability, source, controllerId, game)) .collect(Collectors.toList()); Player controller = game.getPlayer(controllerId); if (controller == null) { return false; } switch (usable.size()) { case 0: return false; case 1: selectedCost = usable.get(0); break; case 2: StringBuilder sb = new StringBuilder(); if (usable.get(0) instanceof ManaCost) { sb.append("Pay "); sb.append(usable.get(0).getText()); } else { sb.append(CardUtil.getTextWithFirstCharUpperCase(usable.get(0).getText())); } sb.append(" or "); sb.append(usable.get(1).getText()); sb.append('?'); if (controller.chooseUse( Outcome.Detriment, sb.toString(), null, CardUtil.getTextWithFirstCharUpperCase(usable.get(0).getText()), CardUtil.getTextWithFirstCharUpperCase(usable.get(1).getText()), ability, game )) { selectedCost = usable.get(0); } else { selectedCost = usable.get(1); } break; default: Map costMap = usable .stream() .collect(Collectors.toMap(Cost::getText, Function.identity())); Choice choice = new ChoiceImpl(true); choice.setMessage("Choose a cost to pay"); choice.setChoices(costMap .keySet() .stream() .map(CardUtil::getTextWithFirstCharUpperCase) .collect(Collectors.toSet())); controller.choose(Outcome.Neutral, choice, game); selectedCost = costMap.getOrDefault( CardUtil.getTextWithFirstCharLowerCase(choice.getChoice()), null ); } if (selectedCost == null) { return false; } return selectedCost.pay(ability, game, source, controllerId, noMana, costToPay); } @Override public boolean isPaid() { return selectedCost != null ? selectedCost.isPaid() : false; } @Override public void clearPaid() { selectedCost = null; costs.forEach(Cost::clearPaid); } @Override public void setPaid() { if (selectedCost != null) { selectedCost.setPaid(); } } @Override public Targets getTargets() { if (selectedCost != null) { return selectedCost.getTargets(); } return new Targets().withReadOnly(); } @Override public OrCost copy() { return new OrCost(this); } }