# -*- coding: utf-8 -*-
# Copyright 2021 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Objects for describing template code to be generated from structured.xml."""

import hashlib
import os
import re
import struct

import templates_validator as validator_tmpl


class Util:
  """Helpers for generating C++."""

  @staticmethod
  def sanitize_name(name):
    return re.sub('[^0-9a-zA-Z_]', '_', name)

  @staticmethod
  def camel_to_snake(name):
    pat = '((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))'
    return re.sub(pat, r'_\1', name).lower()

  @staticmethod
  def hash_name(name):
    # This must match the hash function in chromium's
    # //base/metrics/metric_hashes.cc. >Q means 8 bytes, big endian.
    name = name.encode('utf-8')
    md5 = hashlib.md5(name)
    return struct.unpack('>Q', md5.digest()[:8])[0]

  @staticmethod
  def event_name_hash(project_name, event_name):
    """Make the name hash for an event.

    This gets uploaded in the StructuredEventProto.event_name_hash field. It is
    the sole means of recording which event from structured.xml a
    StructuredEventProto instance represents.

    To avoid naming collisions, it must contain three pieces of information:
     - the name of the event itself
     - the name of the event's project, to avoid collisions with events of the
       same name in other projects
     - an identifier that this comes from chromium, to avoid collisions with
       events and projects of the same name defined in cros's structured.xml

    This must use sanitized names for the project and event.
    """
    event_name = Util.sanitize_name(event_name)
    project_name = Util.sanitize_name(project_name)
    # TODO(crbug.com/1148168): Once the minimum python version is 3.6+, rewrite
    # this .format and others using f-strings.
    return Util.hash_name('chrome::{}::{}'.format(project_name, event_name))


class FileInfo:
  """Codegen-related info about a file."""

  def __init__(self, dirname, basename):
    self.dirname = dirname
    self.basename = basename
    self.rootname = os.path.splitext(self.basename)[0]
    self.filepath = os.path.join(dirname, basename)


    # This takes the last three components of the filepath for use in the
    # header guard, ie. METRICS_STRUCTURED_STRUCTURED_EVENTS_H_
    relative_path = os.sep.join(self.filepath.split(os.sep)[-3:])
    self.guard_path = Util.sanitize_name(relative_path).upper()


class ProjectInfo:
  """Codegen-related info about a project."""

  def __init__(self, project):
    self.name = Util.sanitize_name(project.name)
    self.namespace = Util.camel_to_snake(self.name)
    self.name_hash = Util.hash_name(self.name)
    self.validator = '{}ProjectValidator'.format(self.name)
    self.validator_snake_name = Util.camel_to_snake(self.validator)
    self.events = project.events

    # Set ID type.
    if project.id == 'uma':
      self.id_type = 'kUmaId'
    elif project.id == 'per-project':
      self.id_type = 'kProjectId'
    elif project.id == 'none':
      self.id_type = 'kUnidentified'
    else:
      raise ValueError('Invalid id type.')

    # Set ID scope
    if project.scope == 'profile':
      self.id_scope = 'kPerProfile'
    elif project.scope == 'device':
      self.id_scope = 'kPerDevice'
    else:
      raise ValueError('Invalid id scope.')

    # Set event type. This is inferred by checking all metrics within the
    # project. If any of a project's metrics is a raw string, then its events
    # are considered raw string events, even if they also contain non-strings.
    self.event_type = 'REGULAR'
    for event in project.events:
      for metric in event.metrics:
        if metric.type == 'raw-string':
          self.event_type = 'RAW_STRING'
          break

    # Check if event is part of an event sequence. Note that this goes after the
    # raw string check since the type has higher priority.
    if project.is_event_sequence_project:
      self.is_event_sequence = 'true'
      self.event_type = 'SEQUENCE'
    else:
      self.is_event_sequence = 'false'

    self.key_rotation_period = project.key_rotation_period

  def build_event_map(self) -> str:
    event_infos = (EventInfo(event, self) for event in self.events)

    # Generate map entries.
    validator_map_str = ',\n  '.join(
        '{{"{}", &{}}}'.format(event_info.name, event_info.validator_snake_name)
        for event_info in event_infos)
    return validator_tmpl.IMPL_PROJECT_EVENT_MAP_TEMPLATE.format(
        project=self, event_validator_map=validator_map_str)

  def build_event_validators(self) -> str:
    event_infos = (EventInfo(event, self) for event in self.events)
    return '\n'.join(event.build_validator_init() for event in event_infos)

  def build_project_init(self) -> str:
    return 'static {} {};'.format(self.validator, self.validator_snake_name)

  def build_validator_code(self) -> str:
    return validator_tmpl.IMPL_PROJECT_VALIDATOR_TEMPLATE.format(project=self)


class EventInfo:
  """Codegen-related info about an event."""

  def __init__(self, event, project_info):
    self.name = Util.sanitize_name(event.name)
    self.name_hash = Util.event_name_hash(project_info.name, self.name)
    self.validator_name = '{}EventValidator'.format(self.name)
    self.validator_snake_name = Util.camel_to_snake(self.validator_name)
    self.project_name = project_info.name
    self.is_event_sequence = project_info.is_event_sequence
    self.metrics = event.metrics

  def build_metric_hash_map(self) -> str:
    metric_infos = (MetricInfo(metric) for metric in self.metrics)
    return ',\n  '.join(
        '{{\"{}\", {{ Event::MetricType::{}, UINT64_C({})}}}}'.format(
            metric_info.name, metric_info.type_enum, metric_info.hash)
        for metric_info in metric_infos)

  def build_validator_init(self) -> str:
    return ('static {} {};').format(self.validator_name,
                                    self.validator_snake_name)

  def build_validator_code(self) -> str:
    if len(self.metrics) > 0:
      metadata_impl = validator_tmpl.IMPL_GET_METRICS_METADATA.format(
          metric_hash_map=self.build_metric_hash_map())
    else:
      metadata_impl = "  return absl::nullopt;"
    return validator_tmpl.IMPL_EVENT_VALIDATOR_TEMPLATE.format(
        event=self, get_metrics_metadata_impl=metadata_impl)


class MetricInfo:
  """Codegen-related info about a metric."""

  def __init__(self, metric):
    self.name = Util.sanitize_name(metric.name)
    self.hash = Util.hash_name(metric.name)

    if metric.type == 'hmac-string':
      self.type = 'std::string&'
      self.setter = 'AddHmacMetric'
      self.type_enum = 'kHmac'
      self.base_value = 'base::Value(value)'
    elif metric.type == 'int':
      self.type = 'int64_t'
      self.setter = 'AddIntMetric'
      self.type_enum = 'kLong'
      self.base_value = 'base::Value(base::NumberToString(value))'
    elif metric.type == 'raw-string':
      self.type = 'std::string&'
      self.setter = 'AddRawStringMetric'
      self.type_enum = 'kRawString'
      self.base_value = 'base::Value(value)'
    elif metric.type == 'double':
      self.type = 'double'
      self.setter = 'AddDoubleMetric'
      self.type_enum = 'kDouble'
      self.base_value = 'base::Value(value)'
    else:
      raise ValueError('Invalid metric type.')


class Template:
  """Template for producing code from structured.xml."""

  def __init__(self, model, dirname, basename, file_template, project_template,
               event_template, metric_template):
    self.model = model
    self.dirname = dirname
    self.basename = basename
    self.file_template = file_template
    self.project_template = project_template
    self.event_template = event_template
    self.metric_template = metric_template

  def write_file(self):
    file_info = FileInfo(self.dirname, self.basename)
    with open(file_info.filepath, 'w') as f:
      f.write(self._stamp_file(file_info))

  def _stamp_file(self, file_info):
    project_code = ''.join(
        self._stamp_project(file_info, p) for p in self.model.projects)

    return self.file_template.format(file=file_info, project_code=project_code)

  def _stamp_project(self, file_info, project):
    project_info = ProjectInfo(project)
    event_code = ''.join(
        self._stamp_event(file_info, project_info, event)
        for event in project.events)
    return self.project_template.format(file=file_info,
                                        project=project_info,
                                        event_code=event_code)

  def _stamp_event(self, file_info, project_info, event):
    event_info = EventInfo(event, project_info)
    metric_code = ''.join(
        self._stamp_metric(file_info, event_info, metric)
        for metric in event.metrics)
    return self.event_template.format(file=file_info,
                                      project=project_info,
                                      event=event_info,
                                      metric_code=metric_code)

  def _stamp_metric(self, file_info, event_info, metric):
    return self.metric_template.format(file=file_info,
                                       event=event_info,
                                       metric=MetricInfo(metric))


class ValidatorHeaderTemplate:
  """Template for generating header validator code from structured.xml."""

  def __init__(self, dirname, basename):
    self.dirname = dirname
    self.basename = basename

  def write_file(self) -> None:
    file_info = FileInfo(self.dirname, self.basename)
    with open(file_info.filepath, 'w') as f:
      f.write(self._stamp_file(file_info))

  def _stamp_file(self, file_info) -> str:
    return validator_tmpl.HEADER_FILE_TEMPLATE.format(file=file_info)


class ValidatorImplTemplate:
  """Template for generating implementation validator code from structured.xml.

  The generated file will store a static map containing all the validators
  mapped by event name. All validators are initialized statically.

  Almost everything is generated in an anonymous namespace as the generated map
  should not be exposed. The generated code will be in the following order:

    1) EventValidator class implementation.
    2) EventValidator static initialization.
    3) Project map initialization mapping event name to corresponding
    EventValidator.
    4) Project class implementation.
    5) Project validator static initialization.
    6) Map initialization mapping project name to ProjectValidator.
  """

  def __init__(self, structured_model, dirname, basename):
    self.structured_model = structured_model
    self.dirname = dirname
    self.basename = basename
    self.projects = self.structured_model.projects

  def write_file(self) -> None:
    file_info = FileInfo(self.dirname, self.basename)
    with open(file_info.filepath, 'w') as f:
      f.write(self._stamp_file(file_info))

  def _stamp_file(self, file_info) -> str:
    event_code = []
    event_validators = []
    project_event_maps = []
    project_code = []
    project_validators = []

    for project in self.projects:
      project_info = ProjectInfo(project)
      event_infos = (EventInfo(event, project_info) for event in project.events)
      project_event_code = '\n'.join(event_info.build_validator_code()
                                     for event_info in event_infos)

      event_code.append(project_event_code)
      event_validators.append(project_info.build_event_validators())
      project_event_maps.append(project_info.build_event_map())
      project_code.append(project_info.build_validator_code())
      project_validators.append(project_info.build_project_init())

    # Turn all lists into strings.
    events_code_str = ''.join(event_code)
    event_validators_str = '\n'.join(event_validators)
    project_event_maps_str = '\n'.join(project_event_maps)
    project_code_str = ''.join(project_code)
    project_validators_str = '\n'.join(project_validators)

    return validator_tmpl.IMPL_FILE_TEMPLATE.format(
        file=file_info,
        projects_code=project_code_str,
        event_code=events_code_str,
        event_validators=event_validators_str,
        project_event_maps=project_event_maps_str,
        project_validators=project_validators_str,
        project_map=self._build_project_map())

  def _build_project_map(self) -> str:
    project_infos = (ProjectInfo(project) for project in self.projects)
    project_map = ',\n  '.join(
        '{{"{}", &{}}}'.format(project.name, project.validator_snake_name)
        for project in project_infos)
    return validator_tmpl.IMPL_PROJECT_MAP_TEMPLATE.format(
        project_map=project_map)
