module AR
  module Game

    class Buff < ARObject
      def initialize id=nil
        super
        add_behavior AR::Game::BuffBehavior
      end
    end

    class BuffRemovesOnEvent < Buff
      attr_accessor :conditions
      def initialize event_class, conditions=[], id=nil
        super id
        self.conditions = conditions

        s = AR::Events::Subscription.new event_class: event_class do |e| 
          if self.conditions.empty?
            conditions_met = true
          else
            #call each condition
            conditions_met = !self.conditions.map{|c| c.call(e) }.select{|met| !!met}.empty? 

          end
          AR::Events::BuffRemoved.new buff: self, subject: self.subject if conditions_met
        end
        self.subscriptions.push(s)
      end
    end


    class PoisonBuff < BuffRemovesOnEvent
      def initialize id=nil
        super(AR::Events::ItemConsumed)
        self.add_behavior AR::Game::Discoverable
        self.noun = "poison"
        self.article = ""
        self.strength = 1
        self.conditions.push(Proc.new{|e| 
          if e.item.class == AR::Game::Antidote 
            condition = true
          else
            condition = false
          end
        })

        sub = AR::Events::Subscription.new event_class: AR::Events::ClockTickEvent do |e|
          AR::Events::DamageReceived.new damager: self, damaged: self.character, damage_amount: self.strength
        end
        self.subscriptions.push(sub)

        self.on_applied = Proc.new do |character|
          self.character = character
          if self.character == character.world.player
            AR::Events::NarrationEvent.new narration: "You suddenly feel very ill.  You sense a poison working in your system."
          end
        end

        self.on_removed = Proc.new do |character|
          results = []
          results.push(AR::Events::ObjectRemovedFromGame.new ar_object: self)
          results.push(AR::Events::NarrationEvent.new narration: "You are no longer poisoned")
          results
        end

      end

      def character=(obj)
        self.state[:character_id] = obj.id
      end

      def character
        self.world.find self.state[:character_id]
      end
 

      def character_id
        self.state[:character_id]
      end
    
      def strength=(v)
        self.state[:strength] = v 
      end
    
      def strength
        self.state[:strength]
      end
    end

    class DodgeBuff < BuffRemovesOnEvent
      def initialize
        super(AR::Events::HitAttempt)
        self.conditions.push(Proc.new{|e| 
          if e.hitter.id == self.state[:attacker_id]
            condition = true
          else
            condition = false
          end
        })

        mod = AR::Game::GaugeBehavior::Modifier.new value: 0, source: "dodge_reaction"
        self.on_applied = Proc.new do |avoidance_gauge|
          mod.value = self.state[:value].to_i
          avoidance_gauge.add_modifier mod
          nil
        end
        self.on_removed = Proc.new do |avoidance_gauge|
          avoidance_gauge.remove_modifier mod
          AR::Events::ObjectRemovedFromGame.new ar_object: self
        end

      end

      def attacker=(obj)
        self.state[:attacker_id] = obj.id
      end
      def value=(v)
        self.state[:value] = v 
      end

    end

    class BlockBuff < BuffRemovesOnEvent
      def initialize
        super(AR::Events::HitAttempt)
        self.conditions.push(Proc.new{|e| 
          if e.hitter.id == self.state[:attacker_id]
            condition = true
          else
            condition = false
          end
        })

        mod = AR::Game::GaugeBehavior::Modifier.new value: 0, source: "block_reaction"
        self.on_applied = Proc.new do |dmg_resist_gauge|
          mod.value = self.state[:value].to_i
          dmg_resist_gauge.add_modifier mod
          nil
        end

        self.on_removed = Proc.new do |dmg_resist_gauge|
          dmg_resist_gauge.remove_modifier mod
          AR::Events::ObjectRemovedFromGame.new ar_object: self
        end

      end

      def attacker=(obj)
        self.state[:attacker_id] = obj.id
      end
      def value=(v)
        self.state[:value] = v 
      end

    end

    class ResistanceBuff < BuffRemovesOnEvent
      
      def initialize strength, duration
        super(AR::Events::ClockTickEvent)

        self.state[:ticks_since_applied] = 0
        self.conditions.push(Proc.new{|e| 
          if self.state[:ticks_since_applied] > duration
            true
          else
            false
          end
        })


        mod = AR::Game::GaugeBehavior::Modifier.new value: 0, source: "res_buff_#{self.id}"
        self.on_applied = Proc.new do |dmg_resist_gauge|
          mod.value = strength 
          dmg_resist_gauge.add_modifier mod
          nil
        end

        self.on_removed = Proc.new do |dmg_resist_gauge|
          dmg_resist_gauge.remove_modifier mod
          AR::Events::ObjectRemovedFromGame.new ar_object: self
        end


        sub = AR::Events::Subscription.new event_class: AR::Events::ClockTickEvent do 
          self.state[:ticks_since_applied] += 1
        end
        self.subscriptions << sub
      end


    end






  end

end
