module RateTimeEntryPatch
  def self.included(base) # :nodoc:
    base.extend(ClassMethods)

    base.send(:include, InstanceMethods)

    # Same as typing in the class 
    base.class_eval do
      unloadable # Send unloadable so it will not be unloaded in development
      belongs_to :rate

      before_save :recalculate_cost
      
    end

  end
  
  module ClassMethods
    # Updated the cached cost of all TimeEntries for user and project
    def update_cost_cache(user, project=nil)
      c = ARCondition.new
      c << ["#{TimeEntry.table_name}.user_id = ?", user]
      c << ["#{TimeEntry.table_name}.project_id = ?", project] if project
      
      TimeEntry.all(:conditions => c.conditions).each do |time_entry|
        time_entry.save_cached_cost
      end
    end
  end
  
  module InstanceMethods
    # Returns the current cost of the TimeEntry based on it's rate and hours
    #
    # Is a read-through cache method
    def cost(options={})
      store_to_db = options[:store] || false
      
      unless read_attribute(:cost)
        if self.rate.nil?
          amount = Rate.amount_for(self.user, self.project, self.spent_on.to_s)
        else
          amount = rate.amount
        end

        if amount.nil?
          write_attribute(:cost, 0.0)
        else
          if store_to_db
            # Write the cost to the database for caching
            update_attribute(:cost, amount.to_f * hours.to_f)
          else
            # Cache to object only
            write_attribute(:cost, amount.to_f * hours.to_f)
          end
        end
      end

      read_attribute(:cost)
    end

    def clear_cost_cache
      write_attribute(:cost, nil)
    end
    
    def save_cached_cost
      clear_cost_cache
      update_attribute(:cost, cost)
    end

    def recalculate_cost
      clear_cost_cache
      cost(:store => false)
      true # for callback
    end
    
  end
end


