lib/validators/equal.ex

defmodule Dsv.Equal do
  use Dsv.Validator
  @behaviour Dsv.Comparator

  @moduledoc """
  Dsv.Equal module provides functions to determine if two values are equal.
  """

  message("Values must be equal")

  @doc """

  The `valid?/2` function is designed to evaluate whether two given values are equal.
  This function takes two parameters and compares them to determine if they are equal.
  Check if the two values are equal.

  ## Parameters

    * `data` - The first value to be compared.
    * `options` - The second value to be compared against the first.

  ## Returns

  A boolean value:

  - `true` if `data` is equal to `options`.
  - `false` if `data` is not equal to `options`.

  ## Example
      iex> Dsv.Equal.valid?("text", :text)
      :false

      iex> Dsv.Equal.valid?([], [""])
      :false

      iex> Dsv.Equal.valid?("a", "ab")
      :false

      iex> Dsv.Equal.valid?(nil, "")
      :false

      iex> Dsv.Equal.valid?(%{}, %{"a" => "b"})
      :false

      iex> Dsv.Equal.valid?(%{}, [])
      :false

      iex> Dsv.Equal.valid?(%{}, true)
      :false

      iex> Dsv.Equal.valid?(["elem"], ["elem"])
      :true

      iex> Dsv.Equal.valid?("text", "text")
      :true

      iex> Dsv.Equal.valid?(36, 36)
      :true

      iex> Dsv.Equal.valid?(%{a: :b}, %{a: :b})
      :true

      iex> Dsv.Equal.valid?(~N[2020-10-11 02:12:33], ~N[2020-10-11 02:12:33])
      :true

      iex> Dsv.Equal.valid?(false, false)
      :true

      iex> Dsv.Equal.valid?(nil, nil)
      :true

      iex> Dsv.Equal.valid?(true, true)
      :true

  """
  def valid?(data, options: options), do: Dsv.EqualProto.is_equal(data, options)
  def valid?(data, options), do: Dsv.EqualProto.is_equal(data, options)

  @doc """

  The `validate/2` function is designed to evaluate whether two given values are equal.
  This function takes two parameters and compares them to determine if they are equal.
  Check if the two values are equal.


  ## Parameters

    * `data` - The first value to be compared.
    * `options` - The second value to be compared against the first.

  ## Returns

  - `:ok` if `data` is equal to `options`.
  - `{:error, "Values must be equal"}` if `data` is not equal to `options`.


  ## Example
      iex> Dsv.Equal.validate("text", :text)
      {:error, "Values must be equal"}

      iex> Dsv.Equal.validate([], [""])
      {:error, "Values must be equal"}

      iex> Dsv.Equal.validate("a", "ab")
      {:error, "Values must be equal"}

      iex> Dsv.Equal.validate(nil, "")
      {:error, "Values must be equal"}

      iex> Dsv.Equal.validate(%{}, %{"a" => "b"})
      {:error, "Values must be equal"}

      iex> Dsv.Equal.validate(%{}, [])
      {:error, "Values must be equal"}

      iex> Dsv.Equal.validate(%{}, true)
      {:error, "Values must be equal"}

      iex> Dsv.Equal.validate(["elem"], ["elem"])
      :ok

      iex> Dsv.Equal.validate("text", "text")
      :ok

      iex> Dsv.Equal.validate(36, 36)
      :ok

      iex> Dsv.Equal.validate(%{a: :b}, %{a: :b})
      :ok

      iex> Dsv.Equal.validate(~N[2020-10-11 02:12:33], ~N[2020-10-11 02:12:33])
      :ok

      iex> Dsv.Equal.validate(false, false)
      :ok

      iex> Dsv.Equal.validate(nil, nil)
      :ok

      iex> Dsv.Equal.validate(true, true)
      :ok

  """
  def validate(data, options), do: super(data, options)

  @doc """

  The `validate/3` function is designed to evaluate whether two given values are equal.
  This function takes three parameters and compares first to the second to determine if they are equal, in case of failure it returns third parameter as an error message.
  Check if the two values are equal.


  ## Parameters

    * `data` - The first value to be compared.
    * `options` - The second value to be compared against the first.
    * `message` - Message that will be returned on failure.

  ## Returns

  - `:ok` if `data` is equal to `options`.
  - `{:error, "message"}` if `data` is not equal to `options`.


  ## Example
      iex> Dsv.Equal.validate("text", :text, "Value must be equal to `:text`.")
      {:error, "Value must be equal to `:text`."}

      iex> Dsv.Equal.validate([], [""], "Value must be a list with one empty string element.")
      {:error, "Value must be a list with one empty string element."}

      iex> Dsv.Equal.validate("a", "ab", "Value must be equal to string `ab`.")
      {:error, "Value must be equal to string `ab`."}

      iex> Dsv.Equal.validate(nil, "", "Value must be equal to empty string.")
      {:error, "Value must be equal to empty string."}

      iex> Dsv.Equal.validate(%{}, %{"a" => "b"}, "Value must be a map that contains key `a` and value `b`.")
      {:error, "Value must be a map that contains key `a` and value `b`."}

      iex> Dsv.Equal.validate(%{}, [], "Value must be equal to empty list.")
      {:error, "Value must be equal to empty list."}

      iex> Dsv.Equal.validate(%{}, true, "Value must be equal to true")
      {:error, "Value must be equal to true"}

      iex> Dsv.Equal.validate(["elem"], ["elem"], "Value must be a list with exactly one element equal to string `eleme`.")
      :ok

      iex> Dsv.Equal.validate("text", "text", "Value must be equal to string `text`")
      :ok

      iex> Dsv.Equal.validate(36, 36, "Value must be equal to number `36`")
      :ok

      iex> Dsv.Equal.validate(%{a: :b}, %{a: :b}, "This is not a map I have expected.")
      :ok

      iex> Dsv.Equal.validate(~N[2020-10-11 02:12:33], ~N[2020-10-11 02:12:33], "It isn't the date I was thinking of.")
      :ok

      iex> Dsv.Equal.validate(false, false, "This true is so false.")
      :ok

      iex> Dsv.Equal.validate(nil, nil, "nil would be good")
      :ok

      iex> Dsv.Equal.validate(true, true, "What?")
      :ok

  """
  def validate(data, options, message) when is_bitstring(message),
    do: validate(data, options: options, message: message)

  def validate(data, options, binded_values) when is_map(binded_values),
    do: super(data, options, binded_values)

  @impl Dsv.Comparator
  def to_comparator(value, _options), do: value
end