package magic.model.event;
import magic.model.MagicCardDefinition;
import magic.model.MagicChangeCardDefinition;
import magic.model.MagicCopyMap;
import magic.model.MagicCopyable;
import magic.model.MagicGame;
import magic.model.MagicManaCost;
import magic.model.MagicPayedCost;
import magic.model.MagicPermanent;
import magic.model.MagicPlayer;
import magic.model.MagicSource;
import magic.model.ARG;
import magic.model.action.AddStaticAction;
import magic.model.action.PutItemOnStackAction;
import magic.model.choice.MagicChoice;
import magic.model.condition.MagicCondition;
import magic.model.mstatic.MagicStatic;
import magic.model.stack.MagicAbilityOnStack;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public abstract class MagicPermanentActivation extends MagicActivation<MagicPermanent> implements MagicChangeCardDefinition, MagicCopyable {
public MagicPermanentActivation(final MagicActivationHints hints, final String txt) {
super(MagicActivation.NO_COND,hints,txt);
}
public MagicPermanentActivation(final MagicCondition[] conditions, final MagicActivationHints hints, final String txt) {
super(conditions,hints,txt);
}
@Override
public boolean usesStack() {
return true;
}
@Override
public MagicEvent getEvent(final MagicSource source) {
return new MagicEvent(
source,
this,
EVENT_ACTION,
"Play activated ability of SN."
);
}
@Override
public final boolean canPlay(final MagicGame game, final MagicPlayer player, final MagicPermanent source, final boolean useHints) {
boolean canPlay = super.canPlay(game, player, source, useHints);
// More complex check that first executes events without choice, then check conditions of the others
if (canPlay && source.producesMana()) {
game.snapshot();
for (final MagicEvent event : getCostEvent(source)) {
if (event.hasChoice() == false) {
game.executeEvent(event, MagicEvent.NO_CHOICE_RESULTS);
}
}
for (final MagicEvent event : getCostEvent(source)) {
if (event.hasChoice() == true && event.isSatisfied() == false) {
canPlay = false;
break;
}
}
game.restore();
}
return canPlay;
}
@Override
public MagicCopyable copy(final MagicCopyMap copyMap) {
return this;
}
private static final MagicEventAction EVENT_ACTION = (final MagicGame game, final MagicEvent event) -> {
final MagicPermanentActivation permanentActivation = event.getRefPermanentActivation();
final MagicPermanent permanent = event.getPermanent();
final MagicAbilityOnStack abilityOnStack = new MagicAbilityOnStack(
permanentActivation,
permanent,
game.getPayedCost()
);
game.doAction(new PutItemOnStackAction(abilityOnStack));
};
@Override
public final MagicChoice getChoice(final MagicPermanent source) {
return getPermanentEvent(source,MagicPayedCost.NO_COST).getChoice();
}
public abstract Iterable<? extends MagicEvent> getCostEvent(final MagicPermanent source);
public abstract MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost);
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
throw new RuntimeException(getClass() + " did not override executeEvent");
}
@Override
public void change(final MagicCardDefinition cdef) {
cdef.addAct(this);
}
public static MagicPermanentActivation create(final String act) {
final String[] token = act.split(ARG.COLON, 2);
// build the actual costs
final String costs = token[0];
final List<MagicMatchedCostEvent> matchedCostEvents = MagicRegularCostEvent.build(costs);
assert matchedCostEvents.size() > 0;
// add restriction as a MagicMatchedCostEvent
final String[] part = token[1].split(ActivationRestriction);
for (int i = 1; i < part.length; i++) {
matchedCostEvents.addAll(MagicCondition.build(part[i]));
}
// parse the effect
final String rule = part[0];
final MagicSourceEvent sourceEvent = MagicRuleEventAction.create(rule);
boolean isIndependent = sourceEvent.isIndependent();
for (final MagicMatchedCostEvent matched : matchedCostEvents) {
isIndependent &= matched.isIndependent();
}
return new MagicPermanentActivation(
sourceEvent.getConditions(),
new MagicActivationHints(
sourceEvent.getTiming(),
isIndependent
),
sourceEvent.getName()
) {
@Override
public Iterable<? extends MagicEvent> getCostEvent(final MagicPermanent source) {
final List<MagicEvent> costEvents = new LinkedList<MagicEvent>();
for (final MagicMatchedCostEvent matched : matchedCostEvents) {
costEvents.add(matched.getEvent(source));
}
return costEvents;
}
@Override
public MagicEvent getPermanentEvent(final MagicPermanent source, final MagicPayedCost payedCost) {
return sourceEvent.getEvent(source, payedCost);
}
};
}
public static final MagicPermanentActivation SwitchPT(final MagicManaCost cost) {
return new MagicPermanentActivation(
new MagicActivationHints(MagicTiming.Pump),
"Switch"
) {
@Override
public Iterable<? extends MagicEvent> getCostEvent(final MagicPermanent source) {
return Arrays.asList(new MagicPayManaCostEvent(source,cost));
}
@Override
public MagicEvent getPermanentEvent(final MagicPermanent source,final MagicPayedCost payedCost) {
return new MagicEvent(
source,
this,
"Switch SN's power and toughness until end of turn."
);
}
@Override
public void executeEvent(final MagicGame game, final MagicEvent event) {
game.doAction(new AddStaticAction(event.getPermanent(), MagicStatic.SwitchPT));
}
};
}
}