defmodule GenTimer.Manager do use GenServer require Logger alias GenTimer.{Timer, Messenger} def child_spec({duration, topic}) do %{ id: {__MODULE__, topic}, start: {__MODULE__, :start_link, [{duration, topic}]}, restart: :temporary } end def start_link({duration, topic}) do GenServer.start_link( __MODULE__, {duration, topic}, name: via(topic) ) end def initialize(duration, topic) do DynamicSupervisor.start_child( GenTimer.Supervisor.Manager, {__MODULE__, {duration, topic}} ) end def start(topic) do GenServer.cast(via(topic), :start) end def get_timer(topic) do GenServer.call(via(topic), :get_timer) end def pause(topic) do GenServer.cast(via(topic), :pause) end def reset(topic) do GenServer.cast(via(topic), :reset) end @impl true def init({duration, topic}) do new_timer = duration |> Timer.new() |> Messenger.broadcast(topic) {:ok, {new_timer, topic}} end @impl true def handle_call(:get_timer, _from, {timer, _topic} = state) do {:reply, timer, state} end @impl true def handle_cast(:start, {timer, topic}) do started_timer = timer |> Timer.start() |> Messenger.tick() |> Messenger.broadcast(topic) {:noreply, {started_timer, topic}} end def handle_cast(:pause, {timer, topic}) do paused_timer = timer |> Timer.pause() |> Messenger.broadcast(topic) {:noreply, {paused_timer, topic}} end def handle_cast(:reset, {timer, topic}) do reset_timer = timer |> Timer.reset() |> Messenger.broadcast(topic) {:noreply, {reset_timer, topic}} end @impl true def handle_info(:tick, {timer, topic}) do ticking_timer = timer |> Timer.increment() |> Messenger.tick() |> Messenger.broadcast(topic) if ticking_timer.state == :finished do {:stop, :shutdown, {ticking_timer, topic}} else {:noreply, {ticking_timer, topic}} end end def handle_info(_msg, {timer, topic}) do {:noreply, {timer, topic}} end def via(name) do { :via, Registry, {GenTimer.Registry.Manager, name} } end end