defmodule Outlook.InternalTree.Html do

  alias Outlook.InternalTree.InternalNode
  alias Outlook.InternalTree.TranslationUnit

  @desirable_atts %{"a" => [:href], "img" => [:src]}

  @void_elements ~w(img br hr)

  def strip_attributes([%InternalNode{type: :element} = node | rest]) do
    d_atts = Map.get(@desirable_atts, node.name, [])
    atts = Map.reject(node.attributes, fn {k,_} -> k not in d_atts end)
    [ %{node |
        attributes: atts,
        content: strip_attributes(node.content)
      }
      | strip_attributes(rest) ]
  end

  def strip_attributes([node | rest]) do
    [ node | strip_attributes(rest)]
  end

  def strip_attributes([]), do: []


  def to_html([%{type: :element} = node | rest]) when node.name in @void_elements do
    attr_string = Enum.map_join(node.attributes, "", fn {k,v} -> " #{k}=\"#{v}\"" end)
    "<#{node.name}#{attr_string}>" <> to_html(rest)
  end

  def to_html([%{type: :element} = node | rest]) do
    attr_string = Enum.map_join(node.attributes, "", fn {k,v} -> " #{k}=\"#{v}\"" end)
    "<#{node.name}#{attr_string}>" <>
      to_html(node.content) <>
      "</#{node.name}>" <>
      to_html(rest)
  end

  def to_html([%{type: :text} = node | rest]) do
    node.content <> to_html(rest)
  end

  def to_html([%{type: :comment} = node | rest]) do
    "<!--#{node.content}-->" <> to_html(rest)
  end

  def to_html([%TranslationUnit{} = tunit | rest]) do
    ~s(<span class="tunit" nid="#{tunit.nid}" tu-status="#{tunit.status}">#{tunit.content}</span>) <> to_html(rest)
  end

  def to_html([]), do: ""

  def to_html_preview([ %InternalNode{type: :element} = node | rest], target_id) do
    attr_string = Map.put(node.attributes, :nid, node.nid)
    |> Enum.map_join(" ", fn {k,v} -> "#{k}=\"#{v}\"" end)
    "<#{node.name} #{attr_string}>" <>
      to_html_preview(node.content, target_id) <>
      "</#{node.name}>" <>
      to_html_preview(rest, target_id)
  end

  def to_html_preview([ %InternalNode{type: :text} = node | rest], target_id) do
    ~s(<span nid="#{node.nid}">#{node.content}</span>) <> to_html_preview(rest, target_id)
  end

  def to_html_preview([ %InternalNode{type: :comment} = node | rest], target_id) do
    ~s(<span nid="#{node.nid}"><!--#{node.content}--></span>) <> to_html_preview(rest, target_id)
  end

  def to_html_preview([ %TranslationUnit{} = tunit | rest], target_id) do
    ~s|<span class="tunit" nid="#{tunit.nid}" tu-status="#{tunit.status}" phx-click="select_current_tunit"
       phx-value-nid="#{tunit.nid}" phx-target="#{target_id}">#{tunit.content}</span>| <> to_html_preview(rest, target_id)
  end

  def to_html_preview([], _target_id), do: ""


  def render_doc(tree) do
    OutlookWeb.HtmlDocComponent.render_doc(%{tree: tree})
    |> Phoenix.HTML.Safe.to_iodata()
    |> IO.iodata_to_binary()
  end
end
