require "social_avatar_proxy/avatar_file"
require "social_avatar_proxy/configuration/cache"
require "dalli"
require "digest/md5"

module SocialAvatarProxy
  class Configuration
    class Memcache < Cache
      def read(options = {})
        # generate the key
        file_key = generate_key(options)
        # if the key exists, serve the data
        if data = connection.get(file_key)
          content_type = connection.get("#{file_key}-content-type") || "image/jpeg"
          mtime = connection.get("#{file_key}-mtime") || Time.now
          # serve the avatar file
          AvatarFile.new(file_key).tap do |file|
            begin
              file.write(data)
              file.content_type(content_type)
              file.mtime(mtime)
              file.rewind
            rescue
              file.close
              file.unlink
              raise
            end
          end
        end
      end

      def write(file, options = {})
        # generate the file location
        file_key = generate_key(options)
        # write the file
        connection.set(file_key, file.read)
        # if the file has a content type
        if file.respond_to?(:content_type) && file.content_type
          # write the content type
          connection.set("#{file_key}-content-type", file.content_type)
        end
        # if the file has a modified time
        if file.respond_to?(:mtime) && file.mtime
          # write the content type
          connection.set("#{file_key}-mtime", file.mtime.to_i)
        end
      end

      def initialize
        key do |options|
          pre_hash = "#{options[:service]}-#{options[:identifier]}"
          "#{@namespace || "sap/"}#{Digest::MD5.hexdigest(pre_hash)}"
        end
      end

      private
      # set which Memcached server to use
      # default: "localhost:11211"
      def host(value)
        @host = value
      end
      
      # set the key namespace
      # default: "sap/"
      def namespace(value)
        @namespace = value
      end
      
      # set the key generation block
      # should accept a hash of options
      def key(&block)
        @key = block
      end

      # generate a key given the arguments
      def generate_key(*args)
        @key.yield(*args)
      end
      
      # return a connection to Memcache
      # defaults to a Dalli::Client object
      def connection(value = nil)
        if value
          unless value.respond_to?(:get) && value.respond_to?(:set)
            raise ArgumentError, %Q(
              #{value.inspect}
              must respond to #set and #get
              when using as a Memcache connection
            )
          end
          @connection = value
        end
        @connection ||= Dalli::Client.new(@host || "localhost:11211")
      end
    end
  end
end