lib/storage/adapters/genserver_adapter/unmount.ex

defmodule Sorcery.Storage.GenserverAdapter.Unmount do
  alias Sorcery.Utils.Maps


  def unmount(pid, state) do
    included = get_entities_for_pid(pid, state)
    excluded = get_entities_excluding_pid(pid, state)
    needed_entities = MapSet.difference(excluded, included)
    default_db = Enum.reduce(Map.keys(state.db), %{}, fn k, d -> Map.put(d, k, %{}) end)
    new_db = Enum.reduce(needed_entities, default_db, fn {tk, id}, db ->
      table = Map.get(state.db, tk, %{})
      entity = Map.get(table, id, %{})
      Maps.put_in_p(db, [tk, id], entity)
    end)
    Map.put(state, :db, new_db)
  end


  def get_entities_for_pid(pid, state) do
    portals = 
      Sorcery.Portal.all_portals(state)
      |> Enum.filter(fn %{pid: portal_pid} -> pid == portal_pid end)

    qm = Sorcery.Storage.GenserverAdapter.QueryMeta.new(state)
    db = Sorcery.Storage.GenserverAdapter.Query.solve_portals(portals, qm)
    Enum.reduce(db, MapSet.new([]), fn {tk, table}, acc ->
      ids = Map.keys(table)
      table_entities = Enum.map(ids, fn id -> {tk, id} end) |> MapSet.new()
      MapSet.union(acc, table_entities)
    end)
  end


  def get_entities_excluding_pid(pid, state) do
    portals = 
      Sorcery.Portal.all_portals(state)
      |> Enum.filter(fn %{pid: portal_pid} -> pid != portal_pid end)

    qm = Sorcery.Storage.GenserverAdapter.QueryMeta.new(state)
    db = Sorcery.Storage.GenserverAdapter.Query.solve_portals(portals, qm)
    Enum.reduce(db, MapSet.new([]), fn {tk, table}, acc ->
      ids = Map.keys(table)
      table_entities = Enum.map(ids, fn id -> {tk, id} end) |> MapSet.new()
      MapSet.union(acc, table_entities)
    end)
  end


end