module FDB

def self.api_version(version)

def self.api_version(version)
  header_version = 730
  if self.is_api_version_selected?()
    if @@chosen_version != version
      raise "FDB API already loaded at version #{@@chosen_version}."
    end
    return
  end
  if version < 14
    raise "FDB API versions before 14 are not supported"
  end
  if version > header_version
    raise "Latest known FDB API version is #{header_version}"
  end
  @@chosen_version = version
  require_relative 'fdbimpl'
  err = FDBC.fdb_select_api_version_impl(version, header_version)
  if err.nonzero?
    if err == 2203
      max_supported_version = FDBC.fdb_get_max_api_version()
      if header_version > max_supported_version
        raise "This version of the FoundationDB Ruby binding is not supported by the installed FoundationDB C library. The binding requires a library that supports API version #{header_version}, but the installed library supports a maximum version of #{max_supported_version}."
      else
        raise "API version #{version} is not supported by the installed FoundationDB C library."
      end
    end
    raise "FoundationDB API version error"
  end
  FDBC.init_c_api()
  require_relative 'fdbtuple'
  require_relative 'fdbdirectory'
  if version < 610
    require_relative 'fdbimpl_v609'
  end
  if version > 22
    require_relative 'fdblocality'
  end
  return
end

def self.cb_mutex

def self.cb_mutex
  @@cb_mutex
end

def self.directory

def self.directory 
  @@directory
end

def self.ffi_callbacks

def self.ffi_callbacks
  @@ffi_callbacks
end

def self.get_api_version()

def self.get_api_version()
  if self.is_api_version_selected?()
    return @@chosen_version
  else
    raise "FDB API version not selected"
  end
end

def self.init()

def self.init()
  @@network_thread_monitor.synchronize do
    if !@@network_thread.nil?
      raise Error.new(2000)
    end
    begin
      @@network_thread = Thread.new do
        @@network_thread_monitor.synchronize do
          # Don't start running until init releases this
        end
        # puts "Starting FDB network"
        begin
          FDBC.check_error FDBC.fdb_run_network
        rescue Error => e
          $stderr.puts "Unhandled error in FoundationDB network thread: #{e.to_s}"
        end
      end
      FDBC.check_error FDBC.fdb_setup_network
    rescue
      @@network_thread.kill
      @@network_thread = nil
      raise
    end
  end
  nil
end

def self.is_api_version_selected?()

def self.is_api_version_selected?()
  @@chosen_version >= 0
end

def self.key_to_bytes(k)

def self.key_to_bytes(k)
  if k.respond_to? 'as_foundationdb_key'
    k.as_foundationdb_key
  else
    k
  end
end

def self.open( cluster_file = nil )

def self.open( cluster_file = nil )
  @@network_thread_monitor.synchronize do
    if ! @@network_thread
      init
    end
  end
  @@cache_lock.synchronize do
    if ! @@open_databases.has_key? [cluster_file]
      dpointer = FFI::MemoryPointer.new :pointer
      FDBC.check_error FDBC.fdb_create_database(cluster_file, dpointer)
      @@open_databases[cluster_file] = Database.new dpointer.get_pointer(0)
    end
    @@open_databases[cluster_file]
  end
end

def self.stop()

def self.stop()
  FDBC.check_error FDBC.fdb_stop_network
end

def self.strinc(key)

def self.strinc(key)
	key = key.gsub(/\xff*\z/, '')
	raise ArgumentError, 'Key must contain at least one byte not equal to 0xFF.' if key.length == 0
	key[0..-2] + (key[-1].ord + 1).chr
end

def self.value_to_bytes(v)

def self.value_to_bytes(v)
  if v.respond_to? 'as_foundationdb_value'
    v.as_foundationdb_value
  else
    v
  end
end

def create_cluster(cluster_file_path=nil)

def create_cluster(cluster_file_path=nil)
  Cluster.new cluster_file_path
end

def open( cluster_file = nil, database_name = "DB" )

def open( cluster_file = nil, database_name = "DB" )
  if database_name != "DB"
    raise Error.new(2013) # invalid_database_name
  end
  open_impl(cluster_file)
end