module AR::Game::AiControl 

  #...initialize them here
  def self.init ar_object 
    ar_object.class.attr_serializeable :desires do |desires_array, op, ar_obj|
      case op
      when :load
        desires_array.map do |obj|
         d =  Object.const_get(obj[:type]).new ar_obj
         d.state = obj[:state]
         d.priority = obj[:priority]
         d.assign_to ar_obj
         d
        end      
      when :unload
        desires_array.map do |desire|
          {type: desire.class.to_s, state: desire.state, priority: desire.priority}
        end
      end
    end

    ar_object.desires = []
  end


  def self.extended ar_object
    self.init ar_object
    ar_object.resolutions   << self.choose_action
    ar_object.resolutions   << self.choose_reaction
  end 


  def ai_reaction attacker
    #if choice attack can still be performed, then do choice defense
    #program ai defenses
    if self.action_points > AR::Game::AttackAction.ap_cost || self.last_action.class == AR::Game::AttackAction #default is to defend if ap allows for one attack
      a = AR::Game::DefendAction.new self, attacker
      a.parameter("technique").argument = self.defense_techniques.last
      a
    else
    nil
    end
  end

  def ai_choice 
    wait = AR::Game::WaitAction.new(self)
    if self.dead? 
      AR.log("residual action choice immediately after death of #{self}")
      return nil
    end
    #sort desires by priority, and run an action choice algorithm
    #example:
    #    ["a","c","a","b","c", "D","d",""].sort! { |a,b| a.downcase <=> b.downcase }
    #    => ["", "a", "a", "b", "b", "c", "c", "d", "D"]
    biggest_desire = desires.sort{|d1,d2| d1.priority <=> d2.priority  }.last unless desires.empty?
    choice = nil
    choice = (biggest_desire.call(self)) unless biggest_desire.nil?


    #a = AR::Game::InspectAction.new self
    #a.parameter("target").argument = self.parent

    #the default should be to wait 
    choice || wait
  end


  def self.choose_action 
    AR::Events::Resolution.new event_class: AR::Events::ActorTurnEvent, as: "actor" do  |e|
      actor = e.actor
      results = []
      action = nil 
      action = actor.ai_choice
      
      unless action.nil? or action.class.ap_cost > actor.action_points
        actor.last_action = actor.last_action_this_tick  = action
        results.push(actor.create AR::Events::ActionBeganEvent, ({action: action, performer: actor}))
      else
        actor.last_action_this_tick = AR::Game::WaitAction.new actor
      end
      results
    end
  end

  def self.choose_reaction
    AR::Events::Resolution.new event_class: AR::Events::DefenseChoice, as: "defender" do  |e|
      defender = e.defender
      attacker = e.attacker
      results = []
      action =defender.ai_reaction attacker
      unless action.nil?
        results.push(defender.create AR::Events::ActionBeganEvent, ({action: action}))
      end
      results
    end
  end

end
require_relative "ai_control/desire"
