module Couch

class << self
    def domain
      # TODO(xtang): put this in a couchbase.yaml.
      return "http://#{ENV['COUCHBASE_DOMAIN']}" if ENV['COUCHBASE_DOMAIN']
      
      return APP_CONFIG['couch']['domain']
    end

    def client
      if Rails.env == 'production'
        @client ||= Couchbase.new "#{domain}:8091/pools/default"
      else 
        @client ||= Couchbase.new "#{domain}:8091/pools/default/buckets/#{bucket}"
      end
    end
    
    def bucket
      APP_CONFIG['couch']['bucket']
    end
    
    # return true if coubase is enabled
    def enabled?
      APP_CONFIG[I18n.locale]['global']['config']['couchbase_on'].to_i == 1
    end

    # return true if couchbase is enabled for a specific world.
    def world_enabled?(game_name, wid)
      APP_CONFIG['world_configs'][game_name][wid.to_s]['config']['couchbase_on'].to_i == 1
    end
    
    # return true when it's time to sync the data to mysql database, only needed during the migration.
    def need_to_sync?(last_save)
  	  time_offset = APP_CONFIG[I18n.locale]['global']['time_offset'].to_i
  	  now = (Time.now.to_f - time_offset).to_i
  	  db_sync_threshold = APP_CONFIG[I18n.locale]['global']['db_sync_threshold'] || 900
      return true if last_save.nil? or (now - last_save.to_f).to_i > db_sync_threshold
      # Rails.logger.info "need_to_sync: recently saved."
      return false
    end

    # set a value
    # no-op and return nil if couchbase not enabled
    def set(key, value, wid = 0)
      return nil unless enabled?
      return nil unless wid.to_i == 0 or world_enabled?('Valor', wid)
      client.run do |conn| # asynchronous writes
        client.set(key, value, :format=>:marshal)
      end
    end
    
    def set_multi(input_hash, wid = 0)
      return nil unless enabled?
      return nil unless wid.to_i == 0 or world_enabled?('Valor', wid)
      input_hash.each do |key,value|
        client.run do |conn| # asynchronous writes
          client.set(key, value, :format=>:marshal)
        end
      end
    end

    def delete(key, wid = 0)
      return nil unless enabled?
      return nil unless wid.to_i == 0 or world_enabled?('Valor', wid)
      client.set(key, nil)
    end

    # get a value
    # no-op and return nil if couchbase not enabled
    def get(key, wid = 0)
      return nil unless enabled?
      return nil unless wid.to_i == 0 or world_enabled?('Valor', wid) 
      Timeout::timeout(2) do
        client.get(key)
      end
    end
    
    # get values for all keys and return a hash of {key=>value}
    def get_multi(keys, wid = 0) 
      return nil unless enabled?
      return nil unless keys.size > 0
      return nil unless wid.to_i == 0 or world_enabled?('Valor', wid)
      vals = client.get(keys)
      if (keys.size == 1)
        result_hash = {keys[0] => vals}
      else
        # (0..keys.size-1).each{|i| result_hash[keys[i]] = vals[i]}
        result_hash = Hash[keys.zip(vals)]
      end
      return result_hash
    end
  end
end
