--[[
  This is a (very simple) output template for JSON output.
]]

function tablelength(T)
  local count = 0
  for _ in pairs(T) do count = count + 1 end
  return count
end

function json_encode(s)
  s = string.gsub(s,'\\','\\\\')
  s = string.gsub(s,'"','\\"')
  s = string.gsub(s,"'","\\'")
  s = string.gsub(s,'\n','\\n')
  s = string.gsub(s,'\t','\\t')
  return s
end

function print_aspects(aspects)
  local asp = 1
  nof_aspects = tablelength(aspects)
  for aspect, aspect_details in pairs(aspects) do
    template_print("      \"" .. json_encode(aspect) .. "\" : {\n")
    template_print("        \"successes\" : " ..
                   aspect_details.successes .. ", \n")
    template_print("        \"failures\" : " ..
                   aspect_details.failures .. ", \n")
    template_print("        \"runtime_errors\" : " ..
              aspect_details.runtime_errors .. "")
    if global.show_details then
      local nof_nodes = #aspect_details.nodes
      local nd = 1
      template_print(",\n        \"nodes\" : {\n")
      for n, node in ipairs(aspect_details.nodes) do
        template_print("          \"".. n .. "\" : {\n")
        template_print("            \"filename\" : \"" ..
                       json_encode(node.filename) .. "\",\n")
        template_print("            \"linenumber\" : " ..
                       node.linenumber .. ",\n")
        template_print("            \"failure_messages\" : [\n")
        for c, msg in ipairs(node.failure_messages) do
          template_print("              \"" .. json_encode(msg) .. "\"")
          if c ~= #node.failure_messages then
            template_print(",")
          end
          template_print("\n")
        end
        template_print("             ],\n")
        template_print("            \"runtime_error_messages\" : [\n")
        for c, msg in ipairs(node.runtime_error_messages) do
          template_print("              \"" .. json_encode(msg) .. "\"")
          if c ~= #node.runtime_error_messages then
            template_print(",")
          end
          template_print("\n")
        end
        template_print("             ]\n")
        template_print("           }")
        if nd ~= nof_nodes then
          template_print(",")
        end
        template_print("\n")
        nd = nd + 1
      end
      template_print("         }\n")
    else
      template_print("\n")
    end
    template_print("      }")
    if asp ~= nof_aspects then
      template_print(",")
    end
    template_print("\n")
    asp = asp + 1
  end
end

local nof_feats = tablelength(features)
local nof_regions = tablelength(regions)
local nof_metas = tablelength(metas)
local nof_sequences = tablelength(sequences)
local nof_comments = tablelength(comments)

template_print("{\n")

template_print("  \"features\" : {\n")
local feat = 1
for feature, aspects in pairs(features) do
  template_print("    \"" .. feature .. "\" : {\n")
  print_aspects(aspects)
  template_print("    }")
  if feat ~= nof_feats then
    template_print(",")
  end
  template_print("\n")
  feat = feat + 1
end
template_print("  },\n")

template_print("  \"metas\" : {\n")
print_aspects(metas)
template_print("  },\n")

template_print("  \"regions\" : {\n")
print_aspects(regions)
template_print("  },\n")

template_print("  \"comments\" : {\n")
print_aspects(comments)
template_print("  },\n")

template_print("  \"sequences\" : {\n")
print_aspects(sequences)
template_print("  },\n")

template_print("  \"warnings\" : [\n")
for i, msg in ipairs(warnings) do
  template_print("\"" .. json_encode(msg) .. "\"")
  if i ~= #warnings then
    template_print(", ")
  end
end
template_print("  ],\n")

template_print("  \"runtime\" : " .. global.runtime .. ",\n")
template_print("  \"checked_ccs\" : " .. global.checked_ccs .. ",\n")
template_print("  \"checked_aspects\" : " .. global.checked_aspects .. ",\n")
template_print("  \"checked_types\" : " .. global.checked_types .. ",\n")
template_print("  \"checked_nodes\" : " .. global.checked_nodes .. "\n")

template_print("}\n")
