# Schema as of Mon Nov 27 15:17:56 EST 2006 (schema version 35)
#
#  id                  :integer(11)   not null
#  title               :string(255)   
#  introduction        :text          
#  body_copy           :text          
#  start_date          :date          
#  expert_id           :integer(11)   
#  approved            :binary        
#  lock_version        :integer(11)   default(0)
#  continue_reading    :string(255)   default(Read the full piece)
#

class Topic < ActiveRecord::Base
  belongs_to :expert
  
  has_many :comments, :dependent => :destroy do
    def most_recent()
      find(:first, :order => "#{Comment.table_name}.created_at DESC", :include => :user)
    end
    def total_words
      sum(:word_count)
    end
    def thread_starters
      find(:all, :conditions => "parent_id = 0", :order => "#{Comment.table_name}.created_at DESC", :include => :user)
    end
    def find_three_highest_avg_rating
      find(proxy_owner.comment_ratings.best_average_rated_subject_ids, :include => :user)
    end
  end
  
  has_many :support_materials,  :dependent => :destroy

  has_many :ratings,  :dependent => :destroy, :class_name => 'TopicRating', :foreign_key => 'subject_id',
   :extend => RatingForUserAssociationExtension
  
  has_many :comment_ratings, :through => :comments, :source => :ratings
  
  attr_protected :approved
  
  validates_presence_of :expert
  validates_presence_of :start_date
  validates_length_of :title, :within => 2..255
    
  # is the publish date in the future?
  def for_future?
    self.start_date > Date.today
  end
  
  # can this topic be commented on? (is it approved and past its publish date?)
  def commentable?
    approved? && !for_future?
  end
  
  # can this topic be rated? (calls #commentable?)
  def rateable?
    commentable?
  end
    
  # Cope with invalid dates and MultiparameterAssignmentErrors
  #
  # from http://www.railtie.net/articles/2006/02/22/handling-invalid-dates-with-activerecord-date-helpers
  def attributes=(attributes)
    begin
      super(attributes)
    # Catch the exception from AR::Base
    rescue ActiveRecord::MultiparameterAssignmentErrors => ex
      # Iterarate over the exceptions and remove the invalid field components from the input
      ex.errors.each { |err| attributes.delete_if { |key, value| key =~ /^#{err.attribute}/ } }
      # try again with the bad input fields removed
      super(attributes)   
    end
  end
  
  class << self
    
    def reduce_to_most_commented(topics)
      topics.max{|a,b| a.comments.count <=> b.comments.count}
    end
  
    def reduce_to_most_comment_words(topics)
      topics.max{|a,b| (a.comments.total_words||0) <=> (b.comments.total_words||0) }
    end
  
    def reduce_to_most_rated(topics)
      topics.max{|a,b| a.ratings.count <=> b.ratings.count}
    end
  
    def reduce_to_best_rated(topics)
      topics.min do |a,b| # what about zeros?
        # a.ratings.average(:value, :conditions => 'ratings.value != 77') <=> b.ratings.average(:value, :conditions => 'ratings.value != 77')

        a_rating = a.ratings.average(:value, :conditions => 'ratings.value != 77')
        b_rating = b.ratings.average(:value, :conditions => 'ratings.value != 77')
        
        a_rating = 99 if a_rating == 0
        b_rating = 99 if b_rating == 0
        
        a_rating <=> b_rating
      end
    end
    
    # TODO add find_for_user from medusa branch
  end
  
end
