# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Blink feature-policy presubmit script.

See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into gcl.
"""


import os


def _dynamic_import(module_dir, module_name):
    import sys

    original_sys_path = sys.path
    try:
        sys.path = sys.path + [module_dir]
        return __import__(module_name)
    finally:
        sys.path = original_sys_path


def _import_update_histogram_enum(input_api):
    return _dynamic_import(
        input_api.os_path.join(input_api.PresubmitLocalPath(), '..', '..',
                               '..', '..', '..', 'tools', 'metrics',
                               'histograms'), 'update_histogram_enum')


def _import_path_util(input_api):
    return _dynamic_import(
        input_api.os_path.join(input_api.PresubmitLocalPath(), '..', '..',
                               '..', '..', '..', 'tools', 'metrics', 'common'),
        'path_util')


# Note: this function is copied from third_party/blink/renderer/build/scripts/json5_generator
def _json5_load(lines):
    import re
    import ast
    # Use json5.loads when json5 is available. Currently we use simple
    # regexs to convert well-formed JSON5 to PYL format.
    # Strip away comments and quote unquoted keys.
    re_comment = re.compile(r"^\s*//.*$|//+ .*$", re.MULTILINE)
    re_map_keys = re.compile(r"^\s*([$A-Za-z_][\w]*)\s*:", re.MULTILINE)
    pyl = re.sub(re_map_keys, r"'\1':", re.sub(re_comment, "", lines))
    # Convert map values of true/false to Python version True/False.
    re_true = re.compile(r":\s*true\b")
    re_false = re.compile(r":\s*false\b")
    pyl = re.sub(re_true, ":True", re.sub(re_false, ":False", pyl))
    return ast.literal_eval(pyl)


def _json5_load_from_file(file_path):
    with open(file_path, 'r') as f:
        return _json5_load(f.read())


def uma_histogram_checks_factory(mojom_file, enum_name, update_script_file):
    """
    :param mojom_file: str mojom_file name
    :param enum_name: str enum name used in both mojom file and enums.xml
    :param update_script_file: str update_script_file name
    """

    def run_uma_histogram_checks(input_api, output_api):
        source_path = ''
        for f in input_api.AffectedFiles():
            if f.LocalPath().endswith(mojom_file):
                source_path = f.LocalPath()
                break
        else:
            return []

        start_marker = '^enum {} {{'.format(enum_name)
        end_marker = '^};'
        presubmit_error = _import_update_histogram_enum(
            input_api).CheckPresubmitErrors(
                histogram_enum_name=enum_name,
                update_script_name=update_script_file,
                source_enum_path=source_path,
                start_marker=start_marker,
                end_marker=end_marker,
                strip_k_prefix=True)
        if presubmit_error:
            return [
                output_api.PresubmitPromptWarning(presubmit_error,
                                                  items=[source_path])
            ]
        return []

    return run_uma_histogram_checks


def json5_config_checks_factory(mojom_source_path, json5_config_path,
                                enum_name, ignore_enums):
    """
    :param mojom_source_path: str a src based path to mojom source file
    :param json5_config_path: str a src based path to json5 config file
    :param enum_name: str enum name used in mojom file
    :param ignore_enums: Set[str] enum names that should be ignored in mojom file.
                                  Enum names should not have 'k' prefixes here.
    """

    def run_json5_config_checks(input_api, output_api):
        # Note:
        # |input_api.change.AffectedFiles()| returns all affected files in a CL.
        # |input_api.AffectedFiles()| only returns affected files under current
        # PRESUBMIT directory.
        affected_paths = {
            f.LocalPath()
            for f in input_api.change.AffectedFiles()
        }
        if mojom_source_path not in affected_paths and json5_config_path not in affected_paths:
            return []

        mojom_enums = set(
            _import_update_histogram_enum(input_api).ReadHistogramValues(
                mojom_source_path,
                start_marker='^enum {} {{'.format(enum_name),
                end_marker='^};',
                strip_k_prefix=True).values()) - ignore_enums

        json5_enums = {
            feature['name']
            for feature in _json5_load_from_file(
                _import_path_util(input_api).GetInputFile(json5_config_path))
            ['data']
        }

        json5_missing_enums = mojom_enums - json5_enums
        mojom_missing_enums = json5_enums - mojom_enums

        json5_messages = "{} are missing in json5 config.\n".format(
            list(json5_missing_enums)) if json5_missing_enums else ""
        mojom_messages = "{} are missing in mojom file.\n".format(
            list(mojom_missing_enums)) if mojom_missing_enums else ""

        return [] if json5_enums == mojom_enums else [
            output_api.PresubmitPromptWarning(
                "{} and {} are out of sync: {}{}".format(
                    json5_config_path, mojom_source_path, json5_messages,
                    mojom_messages),
                items=[mojom_source_path, json5_config_path])
        ]

    return run_json5_config_checks


checks = [
    uma_histogram_checks_factory(
        mojom_file="feature_policy_feature.mojom",
        enum_name="FeaturePolicyFeature",
        update_script_file="update_feature_policy_enum.py"),
    uma_histogram_checks_factory(
        mojom_file="document_policy_feature.mojom",
        enum_name="DocumentPolicyFeature",
        update_script_file="update_document_policy_enum.py"),
    json5_config_checks_factory(
        mojom_source_path=os.path.join('third_party', 'blink', 'public',
                                       'mojom', 'feature_policy',
                                       'feature_policy_feature.mojom'),
        json5_config_path=os.path.join('third_party', 'blink', 'renderer',
                                       'core', 'feature_policy',
                                       'feature_policy_features.json5'),
        enum_name="FeaturePolicyFeature",
        ignore_enums={'NotFound'}),
    json5_config_checks_factory(
        mojom_source_path=os.path.join('third_party', 'blink', 'public',
                                       'mojom', 'feature_policy',
                                       'document_policy_feature.mojom'),
        json5_config_path=os.path.join('third_party', 'blink', 'renderer',
                                       'core', 'feature_policy',
                                       'document_policy_features.json5'),
        enum_name="DocumentPolicyFeature",
        ignore_enums=set()),
]


def CheckChangeOnUpload(input_api, output_api):  # pylint: disable=C0103
    return [
        message for check in checks
        for message in check(input_api, output_api)
    ]


def CheckChangeOnCommit(input_api, output_api):  # pylint: disable=C0103
    return [
        message for check in checks
        for message in check(input_api, output_api)
    ]
