# This is the fourth stage in the pipeline, after analyze.
# It takes the output of the analysis phase (which inclues both the parsed
# Erlang AST forms and the module-wide analysis results) and generates Elixir
# AST along with metadata for codegen. The output is in the form of structures
# defined in ex_data.ex.
#
# Much of the code for the convert phase lives in modules in the convert
# directory.

defmodule Erl2ex.Pipeline.Convert do

  @moduledoc false


  alias Erl2ex.Pipeline.ExModule

  alias Erl2ex.Convert.Context
  alias Erl2ex.Convert.ErlForms
  alias Erl2ex.Convert.ExtForms
  alias Erl2ex.Convert.Headers


  # The entry point of the convert phase. Takes a ModuleData as input and
  # returns an ExModule.

  def module(module_data, opts \\ []) do
    context = Context.build(module_data, opts)
    {forms, context} = module_data.forms
      |> Enum.flat_map_reduce(context, &conv_form/2)
    forms = [Headers.build_header(context.module_data, forms) | forms]
    %ExModule{
      name: module_data.name,
      file_comments: file_comments(context, opts),
      forms: forms
    }
  end


  # Generates comment header for a generate Elixir source file.

  defp file_comments(context, opts) do
    if Keyword.get(opts, :emit_file_headers, true) do
      {{year, month, day}, {hour, minute, second}} =
        :os.timestamp |> :calendar.now_to_local_time
      timestamp = "~4..0B-~2..0B-~2..0B ~2..0B:~2..0B:~2..0B"
        |> :io_lib.format([year, month, day, hour, minute, second])
        |> List.to_string
      [
        "# Generated by erl2ex (http://github.com/dazuma/erl2ex)",
        "# From Erlang source: #{Context.cur_file_path_for_display(context)}",
        "# At: #{timestamp}",
      ]
    else
      []
    end
  end


  defp conv_form({nil, ext_form}, context) do
    ExtForms.conv_form(:erl_syntax.type(ext_form), ext_form, context)
  end

  defp conv_form({erl_form, _ext_form}, context) do
    ErlForms.conv_form(erl_form, context)
  end

end
