   require Logger
 
   alias Geolix.Database.Supervisor, as: DatabaseSupervisor
+
+  @ets_state_name :geolix_database_loader
+  @ets_state_opts [:named_table, :protected, :set, read_concurrency: true]
 
   # GenServer lifecycle
 

  defp load_error_message({:config, :unknown_adapter}), do: "unknown adapter configuration"
  defp load_error_message(reason), do: inspect(reason)

  defp maybe_log_error(%{state: :loaded} = db), do: db

  defp maybe_log_error(%{state: {:error, reason}} = db) do

  end

  def init(databases) do
    :ok = prepare_ets_state()

    :ok =
      databases
      |> Enum.filter(&Map.has_key?(&1, :id))
      |> Enum.each(&register_state(:registered, &1))

    :ok = GenServer.cast(__MODULE__, :reload_databases)

    {:ok, nil}
  end

  # GenServer callbacks

  def handle_call({:get_database, which}, _, state) do
    {:reply, lookup_database(which), state}
  end

  def handle_call({:load_database, db}, _, state) do
    result =
      db
      |> load_database()
      |> register_state(db)

    case result[:state] do
      :loaded -> {:reply, :ok, state}
      {:error, _} = err -> {:reply, err, state}
    end
  end

  def handle_call({:unload_database, which}, _, state) do
    result =
      which
      |> lookup_database()
      |> unload_database()

    {:reply, result, state}
  end

  def handle_call(:loaded, _, state) do
    loaded =
      @ets_state_name
      |> :ets.tab2list()
      |> Enum.filter(fn {_id, db} -> :loaded == Map.get(db, :state) end)
      |> Enum.map(fn {id, _db} -> id end)

    {:reply, loaded, state}
  end

  def handle_call(:registered, _, state) do
    registered =
      @ets_state_name
      |> :ets.tab2list()
      |> Enum.map(fn {id, _db} -> id end)

    {:reply, registered, state}
  end

  def handle_cast(:reload_databases, state) do
    @ets_state_name
    |> :ets.tab2list()
    |> Enum.map(fn {_id, db} ->
      db
      |> load_database()
      |> register_state(db)
      |> maybe_log_error()
    end)

    {:noreply, state}
  end
