class Contribution < ActiveRecord::Base
  POINT_VALUES = {
    'Item' => 3,
    'SwfAsset' => 2,
    'PetType' => 15,
    'PetState' => 10
  }
  
  attr_accessor :contributed

  belongs_to :contributed, :polymorphic => true
  belongs_to :user
  
  scope :recent, order('id DESC')
  
  cattr_reader :per_page
  @@per_page = 30
  
  def point_value
    POINT_VALUES[contributed_type]
  end
  
  CONTRIBUTED_RELATIONSHIPS = {
    'SwfAsset' => 'Item',
    'PetState' => 'PetType'
  }
  CONTRIBUTED_CHILDREN = CONTRIBUTED_RELATIONSHIPS.keys
  CONTRIBUTED_TYPES = CONTRIBUTED_CHILDREN + CONTRIBUTED_RELATIONSHIPS.values
  def self.preload_contributeds_and_parents(contributions, options={})
    options[:scopes] ||= {}
    
    # Initialize the groups we'll be using for quick access
    contributions_by_type = {}
    contributed_by_type = {}
    contributed_by_type_and_id = {}
    needed_ids_by_type = {}
    CONTRIBUTED_TYPES.each do |type|
      contributions_by_type[type] = []
      contributed_by_type[type] = []
      contributed_by_type_and_id[type] = {}
      needed_ids_by_type[type] = []
    end
    
    # Go through the contributions to sort them for future contributed
    # assignment, and so we can know what immediate contributed items we'll
    # need to look up
    contributions.each do |contribution|
      type = contribution.contributed_type
      contributions_by_type[type] << contribution
      needed_ids_by_type[type] << contribution.contributed_id
    end
    
    # Load contributed objects without parents, prepare them for easy access
    # for future assignment to contributions and looking up parents
    CONTRIBUTED_CHILDREN.each do |type|
      scope = options[:scopes][type] || type.constantize.scoped
      scope.find(needed_ids_by_type[type]).each do |contributed|
        contributed_by_type[type] << contributed
        contributed_by_type_and_id[type][contributed.id] = contributed
      end
    end
    
    # Load both parents of the children we just got, and immediately
    # contributed objects of that class. all_by_ids_or_children properly
    # assigns parents to children, as well
    CONTRIBUTED_RELATIONSHIPS.each do |child_type, type|
      scope = options[:scopes][type] || type.constantize.scoped
      ids = needed_ids_by_type[type]
      children = contributed_by_type[child_type]
      scope.all_by_ids_or_children(ids, children).each do |contributed|
        contributed_by_type_and_id[type][contributed.id] = contributed
      end
    end
    
    # Assign contributed objects to contributions
    contributions.each do |contribution|
      type = contribution.contributed_type
      id = contribution.contributed_id
      contribution.contributed = contributed_by_type_and_id[type][id]
    end
  end
end