Skip to main content

lib/kameleoon/client_factory.ex

defmodule Kameleoon.ClientFactory do
  @moduledoc """
  Factory helpers for creating and forgetting Kameleoon clients.
  """

  alias Kameleoon.Client
  alias Kameleoon.Error
  alias Kameleoon.Internal.NativeResult
  alias Kameleoon.Native.Events
  alias Kameleoon.Native.Nif

  @default_config_path "/etc/kameleoon/client-elixir.conf"
  @sdk_version Mix.Project.config()[:version]

  @spec create(String.t(), keyword()) :: {:ok, Client.t()} | {:error, Error.t()}
  def create(site_code, opts \\ []) when is_binary(site_code) do
    {config, config_path} = create_options(opts)

    with {:ok, event_owner} <- Events.ensure_started(),
         {:ok, client} <-
           create_native_client(site_code, config, config_path, event_owner) do
      {:ok, client}
    end
  end

  @spec forget(String.t(), keyword()) :: :ok | {:error, Error.t()}
  @spec forget(binary()) :: :ok | {:error, Error.t()}
  def forget(site_code, opts \\ []) when is_binary(site_code) do
    environment = Keyword.get(opts, :environment)

    with :ok <- NativeResult.ok(Nif.forget_client(site_code, environment)),
         :ok <- Events.forget(site_code, environment) do
      :ok
    end
  end

  defp create_options(opts) do
    cond do
      config = Keyword.get(opts, :config) ->
        {config, nil}

      config_path = Keyword.get(opts, :config_path) ->
        {nil, config_path}

      true ->
        {nil, @default_config_path}
    end
  end

  defp create_native_client(site_code, config, config_path, event_owner) do
    case Nif.create_client(site_code, config, config_path, event_owner, @sdk_version) do
      {native, returned_site_code, environment} ->
        site_code = returned_site_code || site_code

        {:ok,
         %Client{
           native: native,
           site_code: site_code,
           environment: environment,
           events: Events
         }}

      {:error, payload} ->
        NativeResult.error(payload)
    end
  end
end