defmodule Outlook.Translators.Deepl do

  def translate(pid, article, options) do
    send(pid, {:progress, %{progress: 0}})
    credentials = start_translation(article, options)
    status = check_status(pid, credentials)
    translation = get_translation(credentials)
    send(pid, {:translation, %{translation: translation, billed_characters: status.billed_characters}})
    Process.sleep 1000
    send(pid, {:progress, %{progress: nil}})
  end

  def get_usage_counts(auth_key) do
    response = HTTPoison.get!("https://api-free.deepl.com/v2/usage",
      ["Authorization": "DeepL-Auth-Key #{auth_key}"])
    Jason.decode!(response.body, keys: :atoms)
  end

  # @options [ssl: [{:versions, [:'tlsv1.2']}], recv_timeout: 500]

  @doc """
    Upload the content to translate and return document_id and document_key as Map.
  """
  def start_translation content, options do
    form = get_multipart_form(
      [
        {"source_lang", options.source_lang},
        {"target_lang", options.target_lang},
        {"tag_handling", "xml"},
        {"splitting_tags", "tunit"},
        {"file", content, {"form-data", [{:name, "file"}, {:filename, "datei.html"}]}, []}
      ]
    )

    response_raw = HTTPoison.request!(
      :post,
      "https://api-free.deepl.com/v2/document",
      form,
      get_multipart_headers(options.auth_key)
    )
    Jason.decode!(response_raw.body, keys: :atoms)
    |> Map.put(:auth_key, options.auth_key)
  end

  @doc """
    Check the status until translation is "done".
  """
  def check_status pid, credentials do
    response_raw = HTTPoison.request!(
      :post,
      "https://api-free.deepl.com/v2/document/#{credentials.document_id}",
      get_multipart_form([{"document_key", credentials.document_key}]),
      get_multipart_headers(credentials.auth_key)
    )
    response = Jason.decode!(response_raw.body, keys: :atoms)

    require Logger
    case response do
      %{status: "done"} ->
        response
      %{status: status} ->
        Logger.debug "Deepl response: #{response |> inspect}"
        steps = Map.get(response, :seconds_remaining, 1) * 5
        for n <- 0..steps do
          send(pid, {:progress, %{progress: 100 * n / steps, status: status}})
          Process.sleep 200
        end
        check_status(pid, credentials)
      end
  end

  def get_translation credentials do

    response_raw = HTTPoison.request!(
      :post,
      "https://api-free.deepl.com/v2/document/#{credentials.document_id}/result",
      get_multipart_form([{"document_key", credentials.document_key}]),
      get_multipart_headers(credentials.auth_key)
    )
    response_raw.body
  end

  defp get_multipart_form fields do
    {:multipart, fields}
  end

  defp get_multipart_headers(auth_key) do
   [
    "Authorization": "DeepL-Auth-Key #{auth_key}",
    "Content-Type": "multipart/form-data",
    "Transfer-Encoding": "chunked",
   ]
  end
end
