#!/usr/bin/env python3
# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Extracts enums.xml to separate files.

Usage:
  tools/metrics/histograms/split_enums.py <dir_name>

Where <dir_name> is a subdirectory of tools/metrics/histograms/metadata/ where
a new enums.xml file should be populated from enums referenced by the
histograms.xml in that directory.
"""

import io
import logging
import os
import sys
from xml.dom import minidom

sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'common'))

import extract_histograms
import histogram_configuration_model
import histogram_paths
import merge_xml
import path_util

ENUMS_XML_TEMPLATE = """<!--
Copyright 2024 The Chromium Authors
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->

<!--

This file describes the enumerations referenced by entries in histograms.xml for
this directory. Some enums may instead be listed in the central enums.xml file
at src/tools/metrics/histograms/enums.xml when multiple files use them.

For best practices on writing enumerations descriptions, see
https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md#Enum-Histograms

Please follow the instructions in the OWNERS file in this directory to find a
reviewer. If no OWNERS file exists, please consider signing up at
go/reviewing-metrics (Googlers only), as all subdirectories are expected to
have an OWNERS file. As a last resort you can send the CL to
chromium-metrics-reviews@google.com.
-->

<histogram-configuration>

<!-- Enum types -->

<enums>


</enums>

</histogram-configuration>
"""

ENUMS_PATH = path_util.GetInputFile('tools/metrics/histograms/enums.xml')


def _get_enums_from_files(files):
  """Finds the names of all referenced enums from the specified XML files."""
  merged = merge_xml.MergeFiles(files)
  histograms, _ = extract_histograms.ExtractHistogramsFromDom(merged)
  enums_used_in_file = set()
  for histogram_name, data in histograms.items():
    # Skip non-enum histograms.
    if 'enumDetails' not in data:
      continue
    enum_name = data['enumDetails']['name']
    enums_used_in_file.add(enum_name)
  return enums_used_in_file


def _extract_enum_nodes_by_names(enum_names):
  """Returns the <enum> nodes corresponding to the specified names."""
  with io.open(ENUMS_PATH, 'r', encoding='utf-8') as f:
    document = minidom.parse(f)

  enum_nodes = []
  for enum_node in document.getElementsByTagName('enum'):
    if enum_node.attributes['name'].value in enum_names:
      enum_nodes.append(enum_node)

  for node in enum_nodes:
    node.parentNode.removeChild(node)

  xml_with_nodes_removed = histogram_configuration_model.PrettifyTree(document)
  return enum_nodes, xml_with_nodes_removed


def _read_enums_xml_or_blank_template(path):
  """Reads the enums XML file as minidom or a blank template if not found."""
  if not os.path.isfile(path):
    print(f'No existing file at {path}, creating it.')
    return minidom.parseString(ENUMS_XML_TEMPLATE)
  with io.open(path, 'r', encoding='utf-8') as f:
    print(f'Oppening existing file {path}...')
    return minidom.parse(f)


def _move_enums_to_file(enum_nodes, enums_file):
  """Adds enum nodes to `enums_file` and returns the updated XML."""
  document = _read_enums_xml_or_blank_template(enums_file)
  enums_node = document.getElementsByTagName('enums')[0]
  for node in enum_nodes:
    enums_node.appendChild(document.importNode(node, True))
  return histogram_configuration_model.PrettifyTree(document)


def _split_enums(dir_name):
  """Splits out an enums.xml file in the specified directory."""
  histograms_file = path_util.GetInputFile(
      f'tools/metrics/histograms/metadata/{dir_name}/histograms.xml')
  if not os.path.isfile(histograms_file):
    print(f'File {histograms_file} not found! Exiting.')
    return

  enums_file = path_util.GetInputFile(
      f'tools/metrics/histograms/metadata/{dir_name}/enums.xml')

  print(f'Reading XML files...')

  # Get the enums referenced by the given histograms.xml file.
  relevant_files = [histograms_file, ENUMS_PATH]
  if os.path.isfile(enums_file):
    relevant_files.append(enums_file)
  enum_names = _get_enums_from_files(relevant_files)

  # Only move enums that aren't referenced by other files.
  all_enum_names = _get_enums_from_files(
      [f for f in histogram_paths.ALL_XMLS if f != histograms_file])
  candidate_enum_names = enum_names - all_enum_names
  print(f'Found {len(candidate_enum_names)} candidate enums.')

  enum_nodes, updated_full_xml = _extract_enum_nodes_by_names(
      candidate_enum_names)
  # There may be fewer, when some of the enums are not in the common enums.xml
  # file (for example, they may be in the target file already).
  assert len(enum_nodes) <= len(candidate_enum_names)
  print(f'Of these, {len(enum_nodes)} are in the common enums.xml file.')

  new_enums_xml = _move_enums_to_file(enum_nodes, enums_file)

  enums_file_did_not_exist = not os.path.isfile(enums_file)
  print(f'Writing updated file: {enums_file}')
  with open(enums_file, 'w', encoding='utf-8', newline='') as f:
    f.write(new_enums_xml)
  print(f'Writing updated file: {ENUMS_PATH}')
  with open(ENUMS_PATH, 'w', encoding='utf-8', newline='') as f:
    f.write(updated_full_xml)

  print('')
  print(f'Moved {len(enum_nodes)} to {enums_file}.')
  print('')

  if enums_file_did_not_exist:
    print('Please run `git add` on the new enums.xml file:')
    print(f'  git add {enums_file}')
    print('')
    print('Updating histograms_xml_files.gni file...')
    histogram_paths.UpdateHistogramsXmlGniFile()
    print('Done.')


def main():
  logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
  if len(sys.argv) != 2:
    print('Usage split_enums.py <dir_name>')
    return
  _split_enums(sys.argv[1])


if __name__ == '__main__':
  main()
