package net.demilich.metastone.game.cards.costmodifier;
import java.util.ArrayList;
import java.util.List;
import net.demilich.metastone.game.Attribute;
import net.demilich.metastone.game.GameContext;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.cards.CardType;
import net.demilich.metastone.game.entities.Entity;
import net.demilich.metastone.game.entities.minions.Race;
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.TargetPlayer;
import net.demilich.metastone.game.spells.desc.manamodifier.CardCostModifierArg;
import net.demilich.metastone.game.spells.desc.manamodifier.CardCostModifierDesc;
import net.demilich.metastone.game.spells.desc.trigger.EventTriggerDesc;
import net.demilich.metastone.game.spells.desc.valueprovider.AlgebraicOperation;
import net.demilich.metastone.game.spells.trigger.GameEventTrigger;
import net.demilich.metastone.game.spells.trigger.IGameEventListener;
import net.demilich.metastone.game.targeting.EntityReference;
public class CardCostModifier extends CustomCloneable implements IGameEventListener {
private boolean expired;
private int owner;
private EntityReference hostReference;
private GameEventTrigger expirationTrigger;
private CardCostModifierDesc desc;
public CardCostModifier(CardCostModifierDesc desc) {
this.desc = desc;
EventTriggerDesc triggerDesc = (EventTriggerDesc) desc.get(CardCostModifierArg.EXPIRATION_TRIGGER);
if (triggerDesc != null) {
this.expirationTrigger = triggerDesc.create();
}
}
public boolean appliesTo(Card card) {
if (expired) {
return false;
}
if (!getRequiredCardIds().isEmpty() && !getRequiredCardIds().contains(card.getId())) {
return false;
}
if (getRequiredAttribute() != null && !card.hasAttribute(getRequiredAttribute())) {
return false;
}
if (getRequiredRace() != null && card.getAttribute(Attribute.RACE) != getRequiredRace()) {
return false;
}
switch (getTargetPlayer()) {
case BOTH:
break;
case OPPONENT:
if (card.getOwner() == getOwner()) {
return false;
}
break;
case SELF:
if (card.getOwner() != getOwner()) {
return false;
}
break;
default:
break;
}
if (getCardType() == null && !card.getCardType().isCardType(CardType.HERO_POWER)) {
return true;
}
return card.getCardType().isCardType(getCardType());
}
@Override
public boolean canFire(GameEvent event) {
return true;
}
@Override
public CardCostModifier clone() {
CardCostModifier clone = (CardCostModifier) super.clone();
clone.expirationTrigger = expirationTrigger != null ? (GameEventTrigger) expirationTrigger.clone() : null;
return clone;
}
public void expire() {
expired = true;
}
protected Object get(CardCostModifierArg arg) {
return desc.get(arg);
}
protected CardType getCardType() {
return (CardType) desc.get(CardCostModifierArg.CARD_TYPE);
}
@Override
public EntityReference getHostReference() {
return hostReference;
}
public int getMinValue() {
return desc.getInt(CardCostModifierArg.MIN_VALUE);
}
@Override
public int getOwner() {
return owner;
}
protected Attribute getRequiredAttribute() {
return (Attribute) desc.get(CardCostModifierArg.REQUIRED_ATTRIBUTE);
}
@SuppressWarnings("unchecked")
protected List<Integer> getRequiredCardIds() {
if (!desc.contains(CardCostModifierArg.CARD_IDS)) {
return new ArrayList<Integer>();
}
return (List<Integer>) desc.get(CardCostModifierArg.CARD_IDS);
}
protected Race getRequiredRace() {
return (Race) get(CardCostModifierArg.RACE);
}
protected TargetPlayer getTargetPlayer() {
if (!desc.contains(CardCostModifierArg.TARGET_PLAYER)) {
return TargetPlayer.SELF;
}
return (TargetPlayer) desc.get(CardCostModifierArg.TARGET_PLAYER);
}
@Override
public boolean interestedIn(GameEventType eventType) {
if (expirationTrigger == null) {
return false;
}
return eventType == expirationTrigger.interestedIn() || expirationTrigger.interestedIn() == GameEventType.ALL;
}
@Override
public boolean isExpired() {
return expired;
}
@Override
public void onAdd(GameContext context) {
}
@Override
public void onGameEvent(GameEvent event) {
Entity host = event.getGameContext().resolveSingleTarget(getHostReference());
if (expirationTrigger != null && event.getEventType() == expirationTrigger.interestedIn() && expirationTrigger.fires(event, host)) {
expire();
}
}
@Override
public void onRemove(GameContext context) {
expired = true;
}
public int process(Card card, int currentManaCost) {
AlgebraicOperation operation = (AlgebraicOperation) desc.get(CardCostModifierArg.OPERATION);
int value = desc.getInt(CardCostModifierArg.VALUE);
if (operation != null) {
return operation.performOperation(currentManaCost, value);
}
int modifiedManaCost = currentManaCost + desc.getInt(CardCostModifierArg.VALUE);
return modifiedManaCost;
}
@Override
public void setHost(Entity host) {
hostReference = host.getReference();
}
@Override
public void setOwner(int playerIndex) {
this.owner = playerIndex;
if (expirationTrigger != null) {
expirationTrigger.setOwner(playerIndex);
}
}
@Override
public boolean hasPersistentOwner() {
return false;
}
@Override
public boolean oneTurnOnly() {
return false;
}
@Override
public boolean isDelayed() {
return false;
}
@Override
public void delayTimeDown() {
}
@Override
public boolean canFireCondition(GameEvent event) {
if (expirationTrigger != null) {
return expirationTrigger.canFireCondition(event);
}
return true;
}
@Override
public boolean hasCounter() {
return false;
}
@Override
public void countDown() {
}
}