from engine.Match import isCard, isCreature, isLand, isPermanent
from engine.GameEvent import UntapStepEvent, UpkeepStepEvent
from engine.CardRoles import permanent_method
from ActivatedAbility import ActivatedAbility
from StaticAbility import CardStaticAbility
from Target import NoTarget, Target
from Trigger import PhaseTrigger
from EffectsUtilities import do_override, override_effect, do_when, combine
from Limit import no_limit, sorcery_limit
from Cost import ManaCost
 
__all__ = ["attach_artifact", "equip", "fortify", "enchant",
           "optionally_untap", "this_card_doesnt_untap",
           "doesnt_untap_controllers_next_untap_step",
           "doesnt_untap_your_next_untap_step",
           "draw_card_next_upkeep",
           "this_card_is_indestructible"]
 
def attach_artifact(cost, keyword, limit=no_limit):
    if isinstance(cost, str): cost = ManaCost(cost)
    def effects(controller, source):
        yield cost
        target = yield Target(source.target_type, player='you')
        source.attach(target)
        yield
    return ActivatedAbility(effects, limit=limit+sorcery_limit, txt='%s %s'%(keyword, cost), keyword=keyword)
 
equip = lambda cost, limit=no_limit: attach_artifact(cost, "Equip", limit)
fortify = lambda cost, limit=no_limit: attach_artifact(cost, "Fortify", limit)
 
def enchant(target_type, zone="battlefield", player=None):
    def effects(source):
        source.target_type = target_type
        source.target_zone = zone
        source.target_player = player
        source.attach_on_enter = None
        yield lambda: None
    return CardStaticAbility(effects, keyword="Enchant %s in %s"%(target_type, zone), zone="all")
 
# Untapping abilities
@permanent_method
def optionally_untap(target):
    return do_override(target, "canUntapDuringUntapStep", 
            lambda self: self.canUntap() and self.controller.getIntention("Untap %s"%self))
@permanent_method
def doesnt_untap_controllers_next_untap_step(target):
    def canUntap(self):
        canUntap.expire()
        return False
    do_override(target, "canUntapDuringUntapStep", canUntap)
@permanent_method
def doesnt_untap_your_next_untap_step(target):
    # This is different than doesnt_untap_controllers_next_untap_step because it specifies
    # YOU, not controller
    # So we don't set it up until the start of your turn, after which it will expire
    controller = target.controller # save the current controller
    def canUntap(self):
        canUntap.expire()
        return False
    do_when(lambda: do_override(target, "canUntapDuringUntapStep", canUntap), UntapStepEvent(), lambda player: player==controller)
 
def this_card_doesnt_untap():
    return CardStaticAbility(effects=override_effect("canUntapDuringUntapStep", lambda self: False), txt="~ doesn't untap during your untap step.")
 
# draw a card at the beginning of the next turn's upkeep
def draw_card_next_upkeep():
    def effects(controller, source):
        '''Draw a card at the beginning of the next turn's upkeep'''
        target = yield NoTarget()
        controller.draw(1)
        yield
    return PhaseTrigger(UpkeepStepEvent()), effects
 
@permanent_method
def indestructible(target):
    def shouldDestroy(self): return False
    def destroy(self, regenerate=True): return False
    return combine(do_override(target, "shouldDestroy", shouldDestroy), do_override(target, "destroy", destroy))
 
def this_card_is_indestructible():
    def indestructible_effect(target):
        yield target.indestructible()
    return CardStaticAbility(effects=indestructible_effect, txt="~ is indestructible.")
 
#class ThresholdAbility(ActivatedAbility):
#    def __init__(self, card, cost="0", target=None, effects=[], copy_targets=True, limit=None, zone="battlefield"):
#        if limit: limit += ThresholdLimit(card)
#        else: limit = ThresholdLimit(card)
#        super(ThresholdAbility,self).__init__(card, cost=cost, target=target, effects=effects, copy_targets=copy_targets, limit=limit, zone=zone)
#
#def vanishing(card, number):
#    for i in range(number): card.counters.append(Counter("time"))
#    remove_counter = TriggeredAbility(card, trigger=PlayerTrigger(event=UpkeepStepEvent()),
#                        match_condition = lambda player, card=card: player == card.controller,
#                        ability=Ability(card, target=Target(targeting="self"), effects=RemoveCounter("time")))
#    def check_time(sender, counter):
#        counters = [c for c in sender.counters if c == "time"]
#        print sender, counter, len(counters)
#        return sender == card and counter == "time" and len(counters) == 0
#
#    sacrifice = TriggeredAbility(card, trigger=Trigger(event=CounterRemovedEvent()),
#                        match_condition = check_time,
#                        ability=Ability(card, effects=SacrificeSelf()))
#    return card.abilities.add([remove_counter, sacrifice])
#
#def dredge(card, number):
#    condition = lambda self: len(self.graveyard) >= number
#    def draw_single(self):
#        if self.getIntention("Would you like to dredge %s?"%card, "Dredge %s"%card):
#            top_N = self.library.top(number)
#            for c in top_N: c.move_to("graveyard")
#            card.move_to("hand")
#        else:
#            self.draw_single()
#
#    dredge_ability = GlobalStaticAbility(card,
#      effects=ReplacementEffect(draw_single, "draw_single", txt='%s - dredge?'%card, expire=False, condition=condition), zone="graveyard")
#    card.abilities.add(dredge_ability)