#!/usr/bin/python3

"""
Generate a table of the Graphviz compile configuration for different platforms
from files generated by the ./configure command.
"""

from argparse import ArgumentParser
import os
import json
import sys
import re

def main(): # pylint: disable=missing-function-docstring
  supported_output_formats = [
      "JSON",
      "HTML",
  ]
  parser = ArgumentParser(description="Generate a table of the Graphviz compile "
                          "configuration for different platforms from files "
                          "generated by the ./configure command.")
  parser.add_argument("--color", "-c", action="store_const",
                      dest="colors", const="green:red",
                      help="Color output using default coloring. Yes is "
                      "colored green and No is colored red")
  parser.add_argument("--colors",
                      help="Color output using specified COLORS. The format is "
                      "<Yes-color>:<No-color>")
  parser.add_argument("--short", "-s", action="store_true",
                      help="Output only Yes or No")
  parser.add_argument("--output-format", default="JSON",
                      choices=supported_output_formats,
                      help="Set output format.")
  parser.add_argument("filename", nargs="*", help="Configuration log to read")

  opts = parser.parse_args()

  if opts.colors is None:
    styles = {
        "Yes": "",
        "No": "",
    }
  else:
    if opts.colors == "":
      yes_color = "green"
      no_color = "red"
    else:
      colors = opts.colors.split(":")
      if len(colors) == 2:
        yes_color, no_color = colors
      else:
        sys.stderr.write(f"Error: {opts.colors} color specification is illegal\n")
        parser.print_help(file=sys.stderr)
        sys.exit(1)
    styles = {
        "Yes": f' style="color: {yes_color};"',
        "No":  f' style="color: {no_color};"',
    }

  table = {}
  table_sections = []
  component_names = {}
  platforms = []

  for filename in opts.filename:
    os_path = os.path.dirname(filename)
    os_version_id = os.path.basename(os_path)
    os_id = os.path.basename(os.path.dirname(os_path))
    platform = f"{os_id.capitalize()} {os_version_id}"
    if platform not in platforms:
      platforms.append(platform)
    with open(filename, "rt", encoding="utf-8") as fp:
      for line in fp.readlines():
        item = [item.strip() for item in line.split(":")]
        if len(item) == 2:
          if item[1] == "":
            section_name = item[0]
            if section_name not in table:
              table[section_name] = {}
              table_sections.append(section_name)
              component_names[section_name] = []
          else:
            component_name, component_value = item
            short_value = re.sub("(Yes|No).*", "\\1", component_value)
            if opts.short:
              component_value = short_value
            if component_name not in table[section_name]:
              table[section_name][component_name] = {}
              component_names[section_name].append(component_name)
            table[section_name][component_name][platform] = component_value

  if opts.output_format == "JSON":
    print(json.dumps(table, indent=4))
  elif opts.output_format == "HTML":
    colspan = len(platforms) + 1
    indent = ""
    print(f"{indent}<!DOCTYPE html>")
    print(f"{indent}<html>")
    indent += "  "
    print(f"{indent}<head>")
    indent += "  "
    print(f'{indent}<meta charset="utf-8">')
    print(f"{indent}<style>")
    indent += "  "
    print(f"{indent}table {{text-align: left; white-space: nowrap; position: relative;}}")
    print(f"{indent}thead tr th {{padding-right: 1em; padding-bottom: 5px; "
          "position: sticky; top: 0px;  background-color: white;}")
    print(f"{indent}td, th {{padding-left: 1.5em;}}")
    indent = indent[:-2]
    print(f"{indent}</style>")
    indent = indent[:-2]
    print(f"{indent}</head>")
    print(f"{indent}<body>")
    indent += "  "
    header = table_sections[0].replace("will be", "was")
    print(f"{indent}<h1>{header}:</h1>")
    print(f"{indent}<table>")
    indent += "  "
    print(f"{indent}<thead>")
    indent += "  "
    print(f"{indent}<tr>")
    indent += "  "
    print(f"{indent}<th></th>")
    for platform in platforms:
      print(f"{indent}<th>{platform}</th>")
    indent = indent[:-2]
    print(f"{indent} </tr>")
    print(f"{indent} </thead>")
    print(f"{indent} <tbody>")
    indent += "  "
    indent = indent[:-2]
    for section_name in table_sections[1:]:
      print(f'{indent}<tr><th colspan="{colspan}">{section_name};</th></tr>')
      for component_name in component_names[section_name]:
        print(f"{indent}<tr>")
        indent += "  "
        print(f"{indent}<td>{component_name}</td>")
        for platform in platforms:
          component_value = table[section_name][component_name][platform]
          short_value = re.sub("(Yes|No).*", "\\1", component_value)
          color_style = styles[short_value]
          print(f"{indent}<td{color_style}>{component_value}</td>")
        indent = indent[:-2]
        print(f"{indent}</tr>")
      print(f'{indent}<tr><th colspan="{colspan}">&nbsp;</th></tr>')
    indent = indent[:-2]
    print(f"{indent}</tbody>")
    indent = indent[:-2]
    print(f"{indent}</table>")
    indent = indent[:-2]
    print(f"{indent}</body>")
    indent = indent[:-2]
    print(f"{indent}</html>")

# Python trick to get a main routine
if __name__ == "__main__":
  main()
