package mage.abilities.decorator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.condition.Condition;
import mage.abilities.condition.FixedCondition;
import mage.abilities.condition.LockedInCondition;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.SubLayer;
import mage.game.Game;
/**
* Adds condition to {@link ContinuousEffect}. Acts as decorator.
*
* @author nantuko
*/
public class ConditionalContinuousEffect extends ContinuousEffectImpl {
protected ContinuousEffect effect;
protected ContinuousEffect otherwiseEffect;
protected Condition baseCondition;
protected Condition condition;
protected boolean initDone = false;
public ConditionalContinuousEffect(ContinuousEffect effect, Condition condition, String text) {
this(effect, null, condition, text);
}
/**
* Only use this if both effects have the same layers
*
* @param effect
* @param otherwiseEffect
* @param condition
* @param text
*/
public ConditionalContinuousEffect(ContinuousEffect effect, ContinuousEffect otherwiseEffect, Condition condition, String text) {
super(effect.getDuration(), effect.getLayer(), effect.getSublayer(), effect.getOutcome());
this.effect = effect;
this.otherwiseEffect = otherwiseEffect;
this.baseCondition = condition;
this.staticText = text;
}
public ConditionalContinuousEffect(final ConditionalContinuousEffect effect) {
super(effect);
this.effect = effect.effect.copy();
if (effect.otherwiseEffect != null) {
this.otherwiseEffect = effect.otherwiseEffect.copy();
}
this.condition = effect.condition;
this.baseCondition = effect.baseCondition;
this.initDone = effect.initDone;
}
@Override
public boolean isDiscarded() {
return this.discarded || effect.isDiscarded() || (otherwiseEffect != null && otherwiseEffect.isDiscarded());
}
@Override
public void init(Ability source, Game game) {
if (baseCondition instanceof LockedInCondition) {
condition = new FixedCondition(((LockedInCondition) baseCondition).getBaseCondition().apply(game, source));
} else {
condition = baseCondition;
}
effect.setTargetPointer(this.targetPointer);
effect.init(source, game);
if (otherwiseEffect != null) {
otherwiseEffect.setTargetPointer(this.targetPointer);
otherwiseEffect.init(source, game);
}
initDone = true;
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
if (!initDone) { // if simpleStaticAbility, init won't be called
init(source, game);
}
boolean conditionState = condition.apply(game, source);
if (conditionState) {
return effect.apply(layer, sublayer, source, game);
} else if (otherwiseEffect != null) {
return otherwiseEffect.apply(layer, sublayer, source, game);
}
if (!conditionState && effect.getDuration() == Duration.OneUse) {
used = true;
}
if (!conditionState && effect.getDuration() == Duration.Custom) {
this.discard();
}
return false;
}
@Override
public boolean apply(Game game, Ability source) {
boolean conditionState = condition.apply(game, source);
if (conditionState) {
effect.setTargetPointer(this.targetPointer);
return effect.apply(game, source);
} else if (otherwiseEffect != null) {
otherwiseEffect.setTargetPointer(this.targetPointer);
return otherwiseEffect.apply(game, source);
}
if (!conditionState && effect.getDuration() == Duration.OneUse) {
used = true;
}
if (!conditionState && effect.getDuration() == Duration.Custom) {
this.discard();
}
return false;
}
@Override
public String getText(Mode mode) {
if ((staticText == null || staticText.isEmpty()) && this.effect != null) { // usefull for conditional night/day card abilities
return effect.getText(mode);
}
return staticText;
}
@Override
public boolean hasLayer(Layer layer) {
return effect.hasLayer(layer);
}
@Override
public ConditionalContinuousEffect copy() {
return new ConditionalContinuousEffect(this);
}
@Override
public Set<UUID> isDependentTo(List<ContinuousEffect> allEffectsInLayer) {
if (effect != null) {
return effect.isDependentTo(allEffectsInLayer);
}
return super.isDependentTo(allEffectsInLayer);
}
}