module RTM::Sugar
  module Role
    module Counterparts
      # This method fetches all roles from the parent association of this role, except itself (i.e. current role).
      # A filter-hash may be used to filter for the type of the other role (:otype =>topic_reference).
      # Examples:
      # this_role.counterparts # returns all
      # this_role.counterparts(:otype => some_topic) # returns only other roles which have type some_topic
      # this_role.counterparts(:otype => "some_reference") # as above, looking up the reference first
      def counterparts(filter={})
        self.parent.roles.reject{|r| r.id==self.id}.
                    select{|r| filter[:otype] ? r.type == self.topic_map.get(filter[:otype]) : true}
      end

      # This methods fetches all players of the parent association of this role, except the player of itself.
      # It accepts a filter-hash like the counterparts-method.
      def counterplayers(*args)
        self.counterparts(*args).map{|r| r.player}
      end

      # Fetches the other role, if the parent association is binary.
      def counterpart
        n = self.parent.roles.size
        raise "Association must be unary or binary to use counterpart method. Please use counterparts for n-ary associations." if n > 2
        return nil if n == 1
        self.counterparts.first
      end
      
      # Fetches the player of the other role, if the parent association is binary.
      def counterplayer
        n = self.parent.roles.size
        raise "Association must be unary or binary to use counterplayer method. Please use counterplayers for n-ary associations." if n > 2
        return nil if n == 1
        self.counterparts.first.player
      end
      
      # Fetches all roles of the (binary) parent associations which play the same role in the same with the counterplayer
      # TODO: filter not only otype but also atype and rtype.
      def peers
        cp = self.counterpart
        cp.player.roles.select{|r| r.type == cp.type}.map{|r| r.counterpart}
      end
      # Fetches all players of roles being in the same association with another topic as self
      # Example: current_role is a role of player "me" and type "employee"
      # current_role.peerplayers # returns all employees of my company (including me)
      def peerplayers
        self.peers.map{|r| r.player}
      end
    end
  end
end