package net.demilich.metastone.game.spells.trigger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.demilich.metastone.game.GameContext;
import net.demilich.metastone.game.entities.Entity;
import net.demilich.metastone.game.events.GameEvent;
import net.demilich.metastone.game.events.GameEventType;
import net.demilich.metastone.game.logic.CustomCloneable;
import net.demilich.metastone.game.spells.desc.SpellDesc;
import net.demilich.metastone.game.targeting.EntityReference;
public class SpellTrigger extends CustomCloneable implements IGameEventListener {
private final static Logger logger = LoggerFactory.getLogger(SpellTrigger.class);
private GameEventTrigger primaryTrigger;
private GameEventTrigger secondaryTrigger;
private SpellDesc spell;
private EntityReference hostReference;
private final boolean oneTurn;
private boolean expired;
private boolean persistentOwner;
private int turnDelay;
public SpellTrigger(GameEventTrigger primaryTrigger, GameEventTrigger secondaryTrigger, SpellDesc spell, boolean oneTurn, int turnDelay) {
this.primaryTrigger = primaryTrigger;
this.secondaryTrigger = secondaryTrigger;
this.spell = spell;
this.oneTurn = oneTurn;
this.turnDelay = turnDelay;
}
public SpellTrigger(GameEventTrigger primaryTrigger, GameEventTrigger secondaryTrigger, SpellDesc spell, boolean oneTurn) {
this(primaryTrigger, secondaryTrigger, spell, oneTurn, 0);
}
public SpellTrigger(GameEventTrigger trigger, SpellDesc spell) {
this(trigger, spell, false, 0);
}
public SpellTrigger(GameEventTrigger trigger, SpellDesc spell, boolean oneTime, int turnDelay) {
this(trigger, null, spell, oneTime, turnDelay);
}
@Override
public SpellTrigger clone() {
SpellTrigger clone = (SpellTrigger) super.clone();
clone.primaryTrigger = (GameEventTrigger) primaryTrigger.clone();
if (secondaryTrigger != null) {
clone.secondaryTrigger = (GameEventTrigger) secondaryTrigger.clone();
}
clone.spell = spell.clone();
return clone;
}
public void expire() {
expired = true;
}
@Override
public EntityReference getHostReference() {
return hostReference;
}
@Override
public int getOwner() {
return primaryTrigger.getOwner();
}
protected SpellDesc getSpell() {
return spell;
}
@Override
public boolean interestedIn(GameEventType eventType) {
boolean result = primaryTrigger.interestedIn() == eventType || primaryTrigger.interestedIn() == GameEventType.ALL;
if (secondaryTrigger != null) {
result |= secondaryTrigger.interestedIn() == eventType || secondaryTrigger.interestedIn() == GameEventType.ALL;
}
return result;
}
@Override
public boolean isExpired() {
return expired;
}
@Override
public void onAdd(GameContext context) {
}
protected void onFire(int ownerId, SpellDesc spell, GameEvent event) {
event.getGameContext().getLogic().castSpell(ownerId, spell, hostReference, null, true);
}
@Override
public void onGameEvent(GameEvent event) {
if (expired) {
return;
}
int ownerId = primaryTrigger.getOwner();
// Expire the trigger beforehand, in case of copying minion (Echoing
// Ooze). Since this method should only be called
// after being checked to be played, copying one-turn triggers should no
// longer matter.
// But let's check to make sure we don't accidentally expire something
// that's still using it.
if (oneTurn && (event.getEventType() == GameEventType.TURN_END || event.getEventType() == GameEventType.TURN_START)) {
expire();
}
try {
if (event.getEventTarget() != null) {
event.getGameContext().getEventTargetStack().push(event.getEventTarget().getReference());
} else {
event.getGameContext().getEventTargetStack().push(null);
}
onFire(ownerId, spell, event);
event.getGameContext().getEventTargetStack().pop();
} catch (Exception e) {
event.getGameContext().printCurrentTriggers();
logger.error("SpellTrigger cannot be executed; GameEventTrigger: {} Spell: {}", primaryTrigger, spell);
throw e;
}
}
@Override
public void onRemove(GameContext context) {
}
@Override
public void setHost(Entity host) {
this.hostReference = host.getReference();
}
@Override
public void setOwner(int playerIndex) {
primaryTrigger.setOwner(playerIndex);
if (secondaryTrigger != null) {
secondaryTrigger.setOwner(playerIndex);
}
}
@Override
public String toString() {
return "[SpellTrigger primaryTrigger=" + primaryTrigger + ", secondaryTrigger=" + secondaryTrigger + ", spell=" + spell
+ ", hostReference=" + hostReference + ", oneTurn=" + oneTurn + ", expired=" + expired + ", persistentOwner="
+ persistentOwner + ", turnDelay=" + turnDelay + "]";
}
@Override
public boolean canFire(GameEvent event) {
if (turnDelay > 0) {
return false;
}
Entity host = event.getGameContext().resolveSingleTarget(hostReference);
return (triggerFires(primaryTrigger, event, host) || triggerFires(secondaryTrigger, event, host));
}
private boolean triggerFires(GameEventTrigger trigger, GameEvent event, Entity host) {
if (trigger == null) {
return false;
}
if (trigger.interestedIn() != event.getEventType() && trigger.interestedIn() != GameEventType.ALL) {
return false;
}
return trigger.fires(event, host);
}
public boolean hasPersistentOwner() {
return persistentOwner;
}
public void setPersistentOwner(boolean persistentOwner) {
this.persistentOwner = persistentOwner;
}
public void delayTimeDown() {
if (turnDelay > 0) {
turnDelay--;
}
}
public boolean isDelayed() {
return turnDelay > 0 ? true : false;
}
public void countDown() {
primaryTrigger.countDown();
if (secondaryTrigger != null) {
secondaryTrigger.countDown();
}
}
public void countDown(int num) {
primaryTrigger.countDown(num);
if (secondaryTrigger != null) {
secondaryTrigger.countDown(num);
}
}
public boolean hasCounter() {
if (secondaryTrigger != null) {
return primaryTrigger.getTriggerCount() > 0 || secondaryTrigger.getTriggerCount() > 0;
}
return primaryTrigger.getTriggerCount() > 0;
}
public boolean oneTurnOnly() {
return oneTurn;
}
public boolean canFireCondition(GameEvent event) {
if (primaryTrigger.canFireCondition(event) || (secondaryTrigger != null && secondaryTrigger.canFireCondition(event))) {
return true;
}
return false;
}
}