# Copyright 2019 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import os
import re
import sys

sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'histograms'))
import extract_histograms
import histogram_paths
import merge_xml


LOCAL_METRIC_RE = re.compile(r'metrics\.([^,]+)')
INVALID_LOCAL_METRIC_FIELD_ERROR = (
  'Invalid index field specification in ukm metric %(event)s:%(metric)s, the '
  'following metrics are used as index fields but are not configured to '
  'support it: [%(invalid_metrics)s]\n\n'
  'See https://chromium.googlesource.com/chromium/src.git/+/main/services/'
  'metrics/ukm_api.md#aggregation-by-metrics-in-the-same-event for '
  'instructions on how to configure them.')


def _isMetricValidAsIndexField(metric_node):
  """Checks if a given metric node can be used as a field in an index tag.

  Has the following requirements:
    * 'history' is the only aggregation target (no others are considered)
    * there will be at most 1 'aggregation', 1 'history', and 1 'statistic'
      element in a metric element
    * enumerations are the only metric types that are valid

  Args:
    metric_node: A metric node to check.

  Returns: True or False, depending on whethere the given node is valid as an
    index field.
  """
  aggregation_nodes = metric_node.getElementsByTagName('aggregation')
  if aggregation_nodes.length != 1:
    return False

  history_nodes = aggregation_nodes[0].getElementsByTagName('history')
  if history_nodes.length != 1:
    return False

  statistic_nodes = history_nodes[0].getElementsByTagName('statistics')
  if statistic_nodes.length != 1:
    return False

  # Only enumeration type metrics are supported as index fields.
  enumeration_nodes = statistic_nodes[0].getElementsByTagName('enumeration')
  return bool(enumeration_nodes)


def _getIndexFields(metric_node):
  """Get a list of fields from index node descendents of a metric_node."""
  aggregation_nodes = metric_node.getElementsByTagName('aggregation')
  if not aggregation_nodes:
    return []

  history_nodes = aggregation_nodes[0].getElementsByTagName('history')
  if not history_nodes:
    return []

  index_nodes = history_nodes[0].getElementsByTagName('index')
  if not index_nodes:
    return []

  return [index_node.getAttribute('fields') for index_node in index_nodes]


def _getLocalMetricIndexFields(metric_node):
  """Gets a set of metric names being used as local-metric index fields."""
  index_fields = _getIndexFields(metric_node)
  local_metric_fields = set()
  for fields in index_fields:
    local_metric_fields.update(LOCAL_METRIC_RE.findall(fields))
  return local_metric_fields


class UkmXmlValidation(object):
  """Validations for the content of ukm.xml."""

  def __init__(self, ukm_config):
    """Attributes:

    config: A XML minidom Element representing the root node of the UKM config
        tree.
    """
    self.config = ukm_config

  def checkEventsHaveOwners(self):
    """Check that every event in the config has at least one owner."""
    errors = []

    for event_node in self.config.getElementsByTagName('event'):
      event_name = event_node.getAttribute('name')
      owner_nodes = event_node.getElementsByTagName('owner')

      # Check <owner> tag is present for each event.
      if not owner_nodes:
        errors.append("<owner> tag is required for event '%s'." % event_name)
        continue

      for owner_node in owner_nodes:
        # Check <owner> tag actually has some content.
        if not owner_node.childNodes:
          errors.append(
              "<owner> tag for event '%s' should not be empty." % event_name)
          continue

        for email in owner_node.childNodes:
          # Check <owner> tag's content is an email address, not a username.
          if not ('@chromium.org' in email.data or '@google.com' in email.data):
            errors.append("<owner> tag for event '%s' expects a Chromium or "
                          "Google email address." % event_name)

    isSuccess = not errors

    return (isSuccess, errors)

  def checkMetricTypeIsSpecified(self):
    """Check each metric is either specified with an enum or a unit."""
    errors = []
    warnings = []

    enum_tree = merge_xml.MergeFiles([histogram_paths.ENUMS_XML])
    enums, _ = extract_histograms.ExtractEnumsFromXmlTree(enum_tree)

    for event_node in self.config.getElementsByTagName('event'):
      for metric_node in event_node.getElementsByTagName('metric'):
        if metric_node.hasAttribute('enum'):
          enum_name = metric_node.getAttribute('enum');
          # Check if the enum is defined in enums.xml.
          if enum_name not in enums:
            errors.append("Unknown enum %s in ukm metric %s:%s." %
                          (enum_name, event_node.getAttribute('name'),
                          metric_node.getAttribute('name')))
        elif not metric_node.hasAttribute('unit'):
          warnings.append("Warning: Neither \'enum\' or \'unit\' is specified "
                          "for ukm metric %s:%s."
                          % (event_node.getAttribute('name'),
                             metric_node.getAttribute('name')))

    isSuccess = not errors
    return (isSuccess, errors, warnings)

  def checkLocalMetricIsAggregated(self):
    """Checks that index fields don't list invalid metrics."""
    errors = []

    for event_node in self.config.getElementsByTagName('event'):
      metric_nodes = event_node.getElementsByTagName('metric')
      valid_index_field_metrics = {node.getAttribute('name')
                                   for node in metric_nodes
                                   if _isMetricValidAsIndexField(node)}
      for metric_node in metric_nodes:
        local_metric_index_fields = _getLocalMetricIndexFields(metric_node)
        invalid_metrics = local_metric_index_fields - valid_index_field_metrics
        if invalid_metrics:
          event_name = event_node.getAttribute('name')
          metric_name = metric_node.getAttribute('name')
          invalid_metrics_string = ', '.join(sorted(invalid_metrics))
          errors.append(INVALID_LOCAL_METRIC_FIELD_ERROR %(
                          {'event': event_name, 'metric': metric_name,
                           'invalid_metrics': invalid_metrics_string}))

    is_success = not errors
    return (is_success, errors)
