module DotHelper
  def render_agents_diagram(agents)
    if (command = ENV['USE_GRAPHVIZ_DOT']) &&
       (svg = IO.popen([command, *%w[-Tsvg -q1 -o/dev/stdout /dev/stdin]], 'w+') { |dot|
          dot.print agents_dot(agents, true)
          dot.close_write
          dot.read
        } rescue false)
      svg.html_safe
    else
      tag('img', src: URI('https://chart.googleapis.com/chart').tap { |uri|
            uri.query = URI.encode_www_form(cht: 'gv', chl: agents_dot(agents))
          })
    end
  end

  private

  def dot_id(string)
    # Backslash escaping seems to work for the backslash itself,
    # despite the DOT language document.
    '"%s"' % string.gsub(/\\/, "\\\\\\\\").gsub(/"/, "\\\\\"")
  end

  def disabled_label(agent)
    agent.disabled? ? dot_id(agent.name + " (Disabled)") : dot_id(agent.name)
  end

  def agents_dot(agents, rich = false)
    "digraph foo {".tap { |dot|
      agents.each.with_index do |agent, index|
        if rich
          dot << '%s[URL=%s];' % [disabled_label(agent), dot_id(agent_path(agent.id))]
        else
          dot << '%s;' % disabled_label(agent)
        end
        agent.receivers.each do |receiver|
          next unless agents.include?(receiver)
          dot << "%s->%s%s;" % [
            disabled_label(agent),
            disabled_label(receiver),
            if rich
              '[style=dashed]' unless receiver.propagate_immediately
            end
          ]
        end
      end
      dot << "}"
    }
  end
end