defmodule Forum.Networks do
  @moduledoc """
  Starts one network process for each forms network the app serves.
  """
  use DynamicSupervisor

  def start_link(opts) do
    DynamicSupervisor.start_link(__MODULE__, opts, name: __MODULE__)
  end

  @impl true
  def init(_opts) do
    DynamicSupervisor.init(strategy: :one_for_one)
  end

  def get_or_start(slug) when is_binary(slug) do
    key = Forum.Network.normalize_slug(slug)

    case Registry.lookup(Forum.ProcessRegistry, {:network, key}) do
      [{pid, _}] ->
        {:ok, pid}

      [] ->
        spec = {Forum.Network, slug: key}

        case DynamicSupervisor.start_child(__MODULE__, spec) do
          {:ok, pid} -> {:ok, pid}
          {:error, {:already_started, pid}} -> {:ok, pid}
          other -> other
        end
    end
  end

  def networks do
    Forum.ProcessRegistry
    |> Registry.select([
      {{{:network, :"$1"}, :"$2", :_}, [], [{{:"$1", :"$2"}}]}
    ])
  end

  def start_networks do
    for slug <- network_slugs() do
      get_or_start(slug)
    end

    :ok
  end

  def network_slugs do
    "networks/*"
    |> Forum.Assets.paths()
    |> Enum.filter(&File.dir?/1)
    |> Enum.map(&Path.basename/1)
    |> Enum.sort()
  end
end
