package net.demilich.metastone.game.spells.trigger;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.demilich.metastone.game.events.GameEvent;
import net.demilich.metastone.game.events.GameEventType;
import net.demilich.metastone.game.spells.aura.Aura;
import net.demilich.metastone.game.targeting.EntityReference;
import net.demilich.metastone.utils.IDisposable;
public class TriggerManager implements Cloneable, IDisposable {
public static Logger logger = LoggerFactory.getLogger(TriggerManager.class);
private final List<IGameEventListener> triggers = new ArrayList<IGameEventListener>();
public TriggerManager() {
}
private TriggerManager(TriggerManager otherTriggerManager) {
for (IGameEventListener gameEventListener : otherTriggerManager.triggers) {
triggers.add(gameEventListener.clone());
}
}
public void addTrigger(IGameEventListener trigger) {
triggers.add(trigger);
if (triggers.size() > 100) {
logger.warn("Warning, many triggers: " + triggers.size() + " adding one of type: " + trigger);
}
}
@Override
public TriggerManager clone() {
return new TriggerManager(this);
}
@Override
public void dispose() {
triggers.clear();
}
public void fireGameEvent(GameEvent event) {
List<IGameEventListener> eventTriggers = new ArrayList<IGameEventListener>();
List<IGameEventListener> removeTriggers = new ArrayList<IGameEventListener>();
for (IGameEventListener trigger : triggers) {
// In order to stop premature expiration, check
// for a oneTurnOnly tag and that it isn't delayed.
if (event.getEventType() == GameEventType.TURN_END) {
if(trigger.oneTurnOnly() && !trigger.isDelayed() &&
!trigger.interestedIn(GameEventType.TURN_START) &&
!trigger.interestedIn(GameEventType.TURN_END)) {
trigger.expire();
}
trigger.delayTimeDown();
}
if (trigger.isExpired()) {
removeTriggers.add(trigger);
}
if (!trigger.interestedIn(event.getEventType())) {
continue;
}
if (triggers.contains(trigger) && trigger.canFire(event)) {
eventTriggers.add(trigger);
}
}
for (IGameEventListener trigger : eventTriggers) {
if (trigger.canFireCondition(event) && triggers.contains(trigger)) {
trigger.countDown();
if (!trigger.hasCounter()) {
trigger.onGameEvent(event);
}
}
// we need to double check here if the trigger still exists;
// after all, a previous trigger may have removed it (i.e. double
// corruption)
if (trigger.isExpired()) {
removeTriggers.add(trigger);
}
}
for (IGameEventListener trigger : removeTriggers) {
triggers.remove(trigger);
}
}
private List<IGameEventListener> getListSnapshot(List<IGameEventListener> triggerList) {
return new ArrayList<IGameEventListener>(triggerList);
}
public List<IGameEventListener> getTriggersAssociatedWith(EntityReference entityReference) {
List<IGameEventListener> relevantTriggers = new ArrayList<>();
for (IGameEventListener trigger : triggers) {
if (trigger.getHostReference().equals(entityReference)) {
relevantTriggers.add(trigger);
}
}
return relevantTriggers;
}
public void printCurrentTriggers() {
for (IGameEventListener trigger : triggers) {
System.out.println();
System.out.println(trigger.toString());
System.out.println();
}
}
public void removeTrigger(IGameEventListener trigger) {
if (!triggers.remove(trigger)) {
System.out.println("Failed to remove trigger " + trigger);
}
}
public void removeTriggersAssociatedWith(EntityReference entityReference, boolean removeAuras) {
for (IGameEventListener trigger : getListSnapshot(triggers)) {
if (trigger.getHostReference().equals(entityReference)) {
if (!removeAuras && trigger instanceof Aura) {
continue;
}
triggers.remove(trigger);
}
}
}
}