#!/usr/bin/python3
"""Script to generate Redfish enum definitions."""

from collections import defaultdict  # pylint: disable=g-importing-member
import os
import re
import shutil
import xml.etree.ElementTree as ET

SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
REDFISH_SCHEMA_DIR = os.path.realpath(
    os.path.join(SCRIPT_DIR, "..", "static", "redfish", "v1", "schema")
)

OUTFOLDER = os.path.realpath(
    os.path.join(
        SCRIPT_DIR, "..", "redfish-core", "include", "generated", "enums"
    )
)

# Odata string types
EDMX = "{http://docs.oasis-open.org/odata/ns/edmx}"
EDM = "{http://docs.oasis-open.org/odata/ns/edm}"


class Enum:

  def __init__(self, name, values, namespace, from_file):
    self.name = name
    self.values = values
    self.namespace = namespace
    self.from_file = from_file


def parse_schema(element, filename):
  """Parses a schema element and returns a list of Enum objects."""
  entity_types = []
  namespace = element.attrib["Namespace"]
  for schema_element in element:
    name = schema_element.attrib.get("Name", None)
    if name is None:
      continue
    if schema_element.tag == EDM + "EnumType":
      enums = []
      for member in schema_element.findall(EDM + "Member"):
        enums.append(member.attrib["Name"])
      entity_types.append(Enum(name, enums, namespace, filename))
  return entity_types


def parse_file(filename):
  print("parse_file: " + filename)
  tree = ET.parse(filename)
  root = tree.getroot()
  results = []
  data_services = root.findall(EDMX + "DataServices")
  for ds in data_services:
    for element in ds:
      if element.tag == EDM + "Schema":
        results.extend(parse_schema(element, filename))

  return results


def camel_to_snake(name):
  # snake casing PCIeDevice and PCIeFunction results in mediocre results
  # given that the standard didn't camel case those in a way that the
  # algorithm expects, so change the casing explicitly to generate sane
  # snake case results.
  name = name.replace("PCIe", "Pcie")
  name = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name)
  return re.sub("([a-z0-9])([A-Z])", r"\1_\2", name).lower()


def write_enum_list(redfish_defs_file, enum_list, snake_case_namespace):
  """Writes the enum list to generated files."""
  redfish_defs_file.write(
      "// NOLINTBEGIN\n"
      "#pragma once\n"
      "#include <cstdint>\n"
      "#include <nlohmann/json.hpp>\n\n"
      "namespace {}\n"
      "{{\n"
      "// clang-format off\n\n".format(snake_case_namespace)
  )

  for element in enum_list:
    redfish_defs_file.write(
        "enum class {} : std::uint8_t{{\n".format(element.name)
    )
    values = element.values
    if "Invalid" not in values:
      values.insert(0, "Invalid")

    for value in values:
      redfish_defs_file.write("    {},\n".format(value))

    redfish_defs_file.write("};\n\n")

  for element in enum_list:
    values = element.values
    if "Invalid" not in values:
      values.insert(0, "Invalid")
    # nlohmann::json aparently uses c style arrays in their enum
    # implementation, and clang-tidy isn't smart enough to figure out that
    # the C arrays are in their code not bmcwebs, so we have to explicitly
    # ignore the error.
    redfish_defs_file.write(
        "NLOHMANN_JSON_SERIALIZE_ENUM({}, {{\n".format(element.name)
    )
    for value in values:
      redfish_defs_file.write(
          '    {{{}::{}, "{}"}},\n'.format(element.name, value, value)  # pylint: disable=duplicate-string-formatting-argument
      )

    redfish_defs_file.write("});\n\n")

    print(element.name)

  redfish_defs_file.write(
      "}} // namespace {}\n// clang-format on\n// NOLINTEND\n".format(
          snake_case_namespace
      )
  )


def generate_enums(flat_list):
  """Generates the enums."""
  # clear out the old results if they exist
  if os.path.exists(OUTFOLDER):
    shutil.rmtree(OUTFOLDER)
  os.makedirs(OUTFOLDER)

  enum_by_namespace = defaultdict(list)

  for element in flat_list:
    if isinstance(element, Enum):
      namespace_split = element.namespace.split(".")[0]
      enum_by_namespace[namespace_split].append(element)

  for namespace, enum_list in enum_by_namespace.items():
    snake_case_namespace = camel_to_snake(namespace)
    outfile = os.path.join(OUTFOLDER, "{}.hpp".format(snake_case_namespace))

    with open(outfile, "w") as redfish_defs:
      write_enum_list(redfish_defs, enum_list, snake_case_namespace)


def main():
  print("Reading from {}".format(REDFISH_SCHEMA_DIR))
  dir_list = os.listdir(REDFISH_SCHEMA_DIR)

  filepaths = [
      os.path.join(REDFISH_SCHEMA_DIR, filename) for filename in dir_list
  ]

  enum_list = []

  for filepath in filepaths:
    out = parse_file(filepath)
    enum_list.extend(out)

  print("Parsing done")

  generate_enums(enum_list)


if __name__ == "__main__":
  main()
