defmodule Patch.Mock.Code.Generators.Frozen do
  @moduledoc """
  Generator for `frozen` modules.

  `frozen` modules are generated by taking the `target` module and renaming it and ensuring
  that any call in the module to itself is sent to the `frozen` module and not the provided
  module.

  The `frozen` module simple acts as a way to call the unaltered original code.  It is only
  used internally to preserve the GenServer module since the internal implementation requires that
  GenServer work as expected.
  """
  alias Patch.Mock.Code
  alias Patch.Mock.Code.Transform
  alias Patch.Mock.Naming

  @doc """
  Generates a new frozen module based on the forms of a provided module.
  """
  @spec generate(abstract_forms :: [Code.form()], module :: module()) :: [Code.form()]
  def generate(abstract_forms, module) do
    frozen_module = Naming.frozen(module)

    abstract_forms
    |> Transform.clean()
    |> Transform.reroute(module, frozen_module)
    |> Transform.rename(frozen_module)
  end

end
