## ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# The MIT License (MIT)
#
# Copyright (c) 2013, 2014 Microsmart (Pty) Ltd
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
## ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
require 'bson'
require 'bson/byte_buffer'
require "ubiquity/database/adapter/version"
require "ubiquity/database/adapter/async"
require 'ubiquity/database/queryable'


module Ubiquity::Database::Adapter
  include Ubiquity::Daemon::Loggable
  log_as 'DB ADAPTER'


  class << self

    ##
    #
    ##
    def print_adapters
      log("Configured adapters:")
      @adapters.each do |k,v|
        log("  #{k}")
      end
    end



    ##
    #
    ##
    def verbose(value)
      @verbose = value
      @adapters ||= {}
      @adapters.each {|k,v| v.verbose = @verbose}
    end


    ##
    #
    ##
    def configure(id, opts)
      @adapters ||= {}
      @verbose ||= false
      throw 'DuplicateAdapterId' if @adapters.include?(id)
      @adapters[id] = Ubiquity::Database::Adapter::Async.new(opts, @verbose)
      log("Configured database adapter id = #{id.inspect}") if @verbose
    end

    ##
    #
    ##
    def configured?(id)
      return false if @adapters.nil?
      @adapters.include?(id)
    end

    ##
    #
    ##
    def find(id, collection, query, opts = {}, &block)
      throw 'NoSuchAdapterId' unless !@adapters.nil? && @adapters.include?(id)
      @adapters[id].find(collection, query, opts, &block)
    end

    ##
    #
    ##
    def find_one(id, collection, query, opts = {})
      throw 'NoSuchAdapterId' unless !@adapters.nil? && @adapters.include?(id)
      @adapters[id].find_one(collection, query, opts)
    end

    ##
    #
    ##
    def remove(id, collection, query, opts = {})
      throw 'NoSuchAdapterId' unless !@adapters.nil? && @adapters.include?(id)
      @adapters[id].remove(collection, query, opts)
    end

    ##
    #
    ##
    def update(id, collection, query, obj, opts = {})
      throw 'NoSuchAdapterId' unless !@adapters.nil? && @adapters.include?(id)
      @adapters[id].update(collection, query, obj, opts)
    end

    ##
    #
    ##
    def upsert(id, collection, query, obj, opts = {})
      throw 'NoSuchAdapterId' unless !@adapters.nil? && @adapters.include?(id)
      @adapters[id].upsert(collection, query, obj, opts)
    end

    ##
    #
    ##
    def insert(id, collection, obj)
      throw 'NoSuchAdapterId' unless !@adapters.nil? && @adapters.include?(id)
      @adapters[id].insert(collection, obj)
    end

  end
end
