defmodule Watcher do
  @moduledoc """
  Polls channels and streams, downloads segments and stores metadata
  """
  alias Schemas.Clip.Video
  alias Ytex.Infodict

  use Supervisor

  @type callbacks :: %{
          start: (Video.t(), Infodict.t() -> :ok),
          stop: (Video.t() -> :ok) | nil
        }

  @doc """
  Start watching a channel.
  """
  @spec start_watching(String.t(), callbacks) ::
          {:ok, pid()} | {:error, :duplicate | :url_not_canon} | :ignore
  def start_watching(chn_url, callbacks) do
    chn_url = String.downcase(chn_url, :ascii)

    DynamicSupervisor.start_child(
      Watcher.Persistent.Supervisor,
      Watcher.Persistent.child_spec(%{
        url: chn_url,
        callbacks: callbacks,
        task_sv: Watcher.TaskSupervisor
      })
    )
  end

  def pid_from_url(url) do
    url = String.downcase(url, :ascii)

    case Registry.lookup(Watcher.Registry, url) do
      [] -> nil
      [{pid, _}] -> pid
    end
  end

  def start_link(opts) do
    {watcher_opts, sv_opts} = Keyword.split(opts, [])
    Supervisor.start_link(__MODULE__, watcher_opts, [{:name, __MODULE__} | sv_opts])
  end

  def init(_opts) do
    children = [
      {Registry, keys: :unique, name: Watcher.Registry},
      {Task.Supervisor, name: Watcher.TaskSupervisor},
      {DynamicSupervisor, name: Watcher.Persistent.Supervisor, max_seconds: 200_000}
    ]

    init_opts = [strategy: :one_for_all]
    Supervisor.init(children, init_opts)
  end
end
