module AR::Game::StoryBehavior 
  #add attr_accessor properties here... 
  attr_accessor :story_changers

  #classes that tell storys should implement to actually define the
  #story script.  This way, we can serialize the story class type
  #and reboot it when a game is loaded
  class Story < Proc
    attr_accessor :event_class
    attr_accessor :as_who
    def initialize opts 
      self.event_class = opts[:event_class] || opts[:when] || opts[:_for]
      self.as_who = opts[:as_who] || opts[:as]
    end
  end

  class StoryImplement
    attr_accessor :stories
    def initialize stories=[]
      self.stories = stories
      if self.stories.empty?
        s=Story.new when: AR::Events::Event, as: "whoever" do |e|
          "story for : #{e}"
        end
        self.stories.push s
      else
        self.story = story
      end
    end

    def yield_story args 
      event = args[:_for] || args[:event]
      as_who = args[:as_who] || args[:as] 
      as_who = as_who.to_s
      valid = valid_stories event.class, as_who 
      valid.map{|s| s.call(event)}.join(" ")
    end

    def valid_stories evt_type, as_who
      stories.select{|s| s.event_class == evt_type and s.as_who == as_who}
    end

    def remove_matching_stories args
      _for = args[:_for] || args[:event_class]
      as_who = args[:as_who] || args[:as]

      story_implements.delete_if do |si|
        si.story.event_class == _for and si.story.as_who == as_who
      end
    end

    def remove_story story
      self.stories.delete story
    end
    def add_story story
      self.stories.push story
    end
  end

  def self.init ar_object
    ar_object.class.attr_serializeable :story_implements do |story_imp_arr, op|
      case op
      when :load
        story_imp_arr.map{|type| Object.const_get(type) }.map(&:new)
      when :unload
        story_imp_arr.map(&:class)
      end
    end
    ar_object.story_implements = []
  end

  def self.extended ar_object
    self.init ar_object
    #add to object's event subscriptions and resolutions here...
  end 

  def add_story_implement story_implement
    return false if self.story_implements.map(&:class).include? story_implement.class
    self.story_implements.push story_implement
  end


  def remove_story_implement story_implement
    if story_implement.class == Class
      self.story_implements.delete_if{|si|si.class == story_implement}
    else
      self.story_implements.delete story_implement
    end
  end

  def story args 
    story_implements.map{|si| si.yield_story args}.join(" ").strip
  end





  def serialized_story_implements
    self.story_implements.map(&:class)
  end

  def serialized_story_changers
    self.story_changers.map{|sc| "#{sc.class}"}
  end



  #add more methods here

end
