##
# A utility wrapper around the MemCache client to simplify cache access.  All
# methods silently ignore MemCache errors.

module Cache
  
  ##
  # Try to return a logger object that does not rely
  # on ActiveRecord for logging.
  def self.logger
    @logger ||= if defined? Rails.logger # Rails 2.1 +
      Rails.logger
    elsif defined? RAILS_DEFAULT_LOGGER # Rails 1.2.2 +
      RAILS_DEFAULT_LOGGER
    else
      ActiveRecord::Base.logger # ... very old Rails.
    end
  end
  ##
  # Returns the object at +key+ from the cache if successful, or nil if either
  # the object is not in the cache or if there was an error attermpting to
  # access the cache.
  #
  # If there is a cache miss and a block is given the result of the block will
  # be stored in the cache with optional +expiry+, using the +add+ method rather
  # than +set+.

  def self.get(key, expiry = 0)
    start_time = Time.now
    value = CACHE.get key
    elapsed = Time.now - start_time
    logger.debug('MemCache Get (%0.6f)  %s' % [elapsed, key])
    if value.nil? and block_given? then
      value = yield
      add key, value, expiry
    end
    value
  rescue MemCache::MemCacheError => err
    logger.debug "MemCache Error: #{err.message}"
    if block_given? then
      value = yield
      put key, value, expiry
    end
    value
  end

  ##
  # Sets +value+ in the cache at +key+, with an optional +expiry+ time in
  # seconds.

  def self.put(key, value, expiry = 0)
    start_time = Time.now
    CACHE.set key, value, expiry
    elapsed = Time.now - start_time
    logger.debug('MemCache Set (%0.6f)  %s' % [elapsed, key])
    value
  rescue MemCache::MemCacheError => err
    ActiveRecord::Base.logger.debug "MemCache Error: #{err.message}"
    nil
  end

  ##
  # Sets +value+ in the cache at +key+, with an optional +expiry+ time in
  # seconds.  If +key+ already exists in cache, returns nil.

  def self.add(key, value, expiry = 0)
    start_time = Time.now
    response = CACHE.add key, value, expiry
    elapsed = Time.now - start_time
    logger.debug('MemCache Add (%0.6f)  %s' % [elapsed, key])
    (response == "STORED\r\n") ? value : nil
  rescue MemCache::MemCacheError => err
    ActiveRecord::Base.logger.debug "MemCache Error: #{err.message}"
    nil
  end

  ##
  # Deletes +key+ from the cache in +delay+ seconds.

  def self.delete(key, delay = nil)
    start_time = Time.now
    CACHE.delete key, delay
    elapsed = Time.now - start_time
    logger.debug('MemCache Delete (%0.6f)  %s' %
                                    [elapsed, key])
    nil
  rescue MemCache::MemCacheError => err
    logger.debug "MemCache Error: #{err.message}"
    nil
  end

  ##
  # Resets all connections to MemCache servers.

  def self.reset
    CACHE.reset
    logger.debug 'MemCache Connections Reset'
    nil
  end

end

