package magic.model.choice;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import magic.exception.UndoClickedException;
import magic.model.IUIGameController;
import magic.model.MagicCard;
import magic.model.MagicCardList;
import magic.model.MagicGame;
import magic.model.MagicPlayer;
import magic.model.MagicSource;
import magic.model.event.MagicEvent;
import magic.model.target.MagicTargetFilter;
import magic.translate.MText;
public class MagicFromCardFilterChoice extends MagicChoice {
// translatable UI text (prefix with _S).
private static final String _S1 = "Choose up to 1 card";
private static final String _S2 = "Choose up to %d cards";
private static final String _S3 = "Choose a card";
private static final String _S4 = "Choose %d cards";
private final MagicTargetFilter<MagicCard> filter;
private final int amount;
private final boolean upTo;
public MagicFromCardFilterChoice(final MagicTargetFilter<MagicCard> aFilter, final int aAmount, final boolean aUpTo, final String description) {
super(genDescription(aAmount, description, aUpTo));
filter = aFilter;
amount = aAmount;
upTo = aUpTo;
}
private static String genDescription(final int amount, final String description, final boolean aUpTo) {
final String paddedDesc = description.isEmpty() ? description : " " + description;
if (aUpTo && amount == 1) {
return _S1 + paddedDesc + ".";
} else if (aUpTo && amount != 1) {
return MText.get(_S2, amount) + paddedDesc + ".";
} else if (!aUpTo && amount == 1) {
return _S3 + paddedDesc + ".";
} else {
return MText.get(_S4, amount) + paddedDesc + ".";
}
}
private void createOptions(
final Collection<Object> options,
final List<MagicCard> cList,
final MagicCard[] cards,
final int count,
final int limit,
final int index
) {
if (count == limit) {
options.add(new MagicCardChoiceResult(cards));
return;
}
final int left = cList.size() - index;
if (count + left < limit) {
return;
}
cards[count] = cList.get(index);
createOptions(options, cList, cards, count + 1, limit, index + 1);
createOptions(options, cList, cards, count, limit, index + 1);
}
private void createOptionsUpTo(
final Collection<Object> options,
final List<MagicCard> cList,
final MagicCard[] cards,
final int count,
final int limit,
final int index
) {
if (index >= cList.size() || count >= limit) {
final MagicCardChoiceResult result = new MagicCardChoiceResult(cards);
//System.out.println("add " + result);
options.add(result);
} else {
final MagicCard first = cList.get(index);
int cnt = 0;
for (int i = 0; index + i < cList.size() && cList.get(index + i).getStateId() == first.getStateId(); i++) {
cnt++;
}
// use 1 to cnt copies of first
for (int i = 0; i < cnt && count + i + 1 <= limit; i++) {
cards[count + i] = cList.get(index + i);
createOptionsUpTo(options, cList, cards, count + i + 1, limit, index + cnt);
}
// use 0 copies of first
for (int i = 0; i < cnt && count + i + 1 <= limit; i++) {
cards[count + i] = null;
}
createOptionsUpTo(options, cList, cards, count, limit, index + cnt);
}
}
// FIXME: need to implement ordering of cards for AI, needed by scry
@Override
Collection<Object> getArtificialOptions(final MagicGame game, final MagicEvent event) {
final MagicPlayer player = event.getPlayer();
final List<Object> options = new ArrayList<>();
final List<MagicCard> oList = player.filterCards(filter);
final List<Boolean> known = new ArrayList<>(oList.size());
//reveal the cards
for (final MagicCard card : oList) {
known.add(card.isGameKnown());
card.setGameKnown(true);
}
final List<MagicCard> cList = new MagicCardList(oList);
Collections.sort(cList);
final int actualAmount = Math.min(amount, cList.size());
if (actualAmount == 0) {
options.add(new MagicCardChoiceResult());
} else if (upTo) {
createOptionsUpTo(options, cList, new MagicCard[actualAmount], 0, actualAmount, 0);
} else {
createOptions(options, cList, new MagicCard[actualAmount], 0, actualAmount, 0);
}
//hide the cards
for (int i = 0; i < oList.size(); i++) {
oList.get(i).setGameKnown(known.get(i));
}
return options;
}
@Override
public Object[] getPlayerChoiceResults(final IUIGameController controller, final MagicGame game, final MagicEvent event) throws UndoClickedException {
final MagicPlayer player = event.getPlayer();
final MagicSource source = event.getSource();
final MagicCardChoiceResult result = new MagicCardChoiceResult();
final List<MagicCard> choiceList = player.filterCards(filter);
final MagicCardList showList = new MagicCardList(choiceList);
final Set<Object> validCards = new HashSet<>(choiceList);
int actualAmount = Math.min(amount, validCards.size());
if (actualAmount == 0) {
controller.showCards(showList);
controller.focusViewers(5);
controller.enableForwardButton();
controller.waitForInput();
controller.clearCards();
controller.focusViewers(0);
return new Object[]{result};
} else {
for (; actualAmount > 0; actualAmount--) {
final String message = result.size() > 0 ? result.toString() + "|" + getDescription() : getDescription();
controller.showCards(showList);
controller.focusViewers(5);
controller.disableActionButton(false);
controller.setValidChoices(validCards, false);
controller.showMessage(source, message);
if (upTo) {
controller.enableForwardButton();
}
controller.waitForInput();
if (controller.isActionClicked()) {
controller.clearCards();
controller.focusViewers(0);
return new Object[]{result};
}
final MagicCard card = controller.getChoiceClicked();
validCards.remove(card);
result.add(card);
}
}
controller.clearCards();
controller.focusViewers(0);
return new Object[]{result};
}
}