lib/roles/caller.ex

defmodule Wampex.Roles.Caller do
  @moduledoc """
  Handles requests and responses for a Caller
  """

  alias Wampex.Role
  alias Wampex.Roles.Dealer.Result
  @behaviour Role

  @call 48
  @cancel 49
  @result 50

  defmodule Call do
    @moduledoc false
    @enforce_keys [:procedure]

    defstruct [:request_id, :procedure, arg_list: [], arg_kw: %{}, options: %{}]

    @type t :: %__MODULE__{
            request_id: integer() | nil,
            procedure: binary(),
            arg_list: list(any()),
            arg_kw: map(),
            options: map()
          }
  end

  defmodule Cancel do
    @moduledoc false
    @enforce_keys [:request_id]
    defstruct [:request_id, options: %{}]

    @type t :: %__MODULE__{
            request_id: integer(),
            options: map()
          }
  end

  @impl true
  def add(roles) do
    Map.put(roles, :caller, %{})
  end

  @spec call(Call.t()) :: Wampex.message()
  def call(%Call{procedure: p, arg_list: al, arg_kw: akw, options: opts}) do
    [@call, opts, p, al, akw]
  end

  @spec cancel(Cancel.t()) :: Wampex.message()
  def cancel(%Cancel{request_id: ri, options: opts}) do
    [@cancel, ri, opts]
  end

  @impl true
  def handle([@result, id, dets]) do
    handle([@result, id, dets, [], %{}])
  end

  @impl true
  def handle([@result, id, dets, arg_l]) do
    handle([@result, id, dets, arg_l, %{}])
  end

  @impl true
  def handle([@result, id, dets, arg_l, arg_kw]) do
    {[{:next_event, :internal, :established}], id,
     %Result{request_id: id, details: dets, arg_list: arg_l, arg_kw: arg_kw}}
  end
end