# -*- coding: utf-8 -*-
# Copyright 2020 The Chromium OS Authors. All rights reserved.
# 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

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 chromeos, to avoid collisions with
           events and projects of the same name defined in chromium'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('cros::{}::{}'.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.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)

        # 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'

        # 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

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)


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'
        elif metric.type == 'int':
            self.type = 'int64_t'
            self.setter = 'AddIntMetric'
        elif metric.type == 'raw-string':
            self.type = 'std::string&'
            self.setter = 'AddRawStringMetric'
        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)

        project_names = sorted([p.name for p in self.model.projects])
        project_hashes_list = ['UINT64_C({})'.format(Util.hash_name(n))
            for n in project_names]
        project_hashes_literal = '{' + ', '.join(project_hashes_list) + '}'

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

    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))
