# Copyright 2019 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Buildgen attribute validation plugin."""


def anything():
    return lambda v: None


def one_of(values):
    return lambda v: (
        "{0} is not in [{1}]".format(v, values) if v not in values else None
    )


def subset_of(values):
    return lambda v: (
        "{0} is not subset of [{1}]".format(v, values)
        if not all(e in values for e in v)
        else None
    )


VALID_ATTRIBUTE_KEYS_MAP = {
    "filegroup": {
        "deps": anything(),
        "headers": anything(),
        "plugin": anything(),
        "public_headers": anything(),
        "src": anything(),
        "uses": anything(),
    },
    "lib": {
        "asm_src": anything(),
        "baselib": anything(),
        "boringssl": one_of((True,)),
        "build_system": anything(),
        "build": anything(),
        "cmake_target": anything(),
        "defaults": anything(),
        "deps_linkage": one_of(("static",)),
        "deps": anything(),
        "dll": one_of((True, "only")),
        "filegroups": anything(),
        "generate_plugin_registry": anything(),
        "headers": anything(),
        "language": one_of(("c", "c++", "csharp")),
        "LDFLAGS": anything(),
        "platforms": subset_of(("linux", "mac", "posix", "windows")),
        "public_headers": anything(),
        "secure": one_of(("check", True, False)),
        "src": anything(),
        "vs_proj_dir": anything(),
        "zlib": one_of((True,)),
    },
    "target": {
        "args": anything(),
        "benchmark": anything(),
        "boringssl": one_of((True,)),
        "build": anything(),
        "ci_platforms": anything(),
        "corpus_dirs": anything(),
        "cpu_cost": anything(),
        "defaults": anything(),
        "deps": anything(),
        "dict": anything(),
        "exclude_configs": anything(),
        "exclude_iomgrs": anything(),
        "excluded_poll_engines": anything(),
        "filegroups": anything(),
        "flaky": one_of((True, False)),
        "gtest": one_of((True, False)),
        "headers": anything(),
        "language": one_of(("c", "c89", "c++", "csharp")),
        "maxlen": anything(),
        "platforms": subset_of(("linux", "mac", "posix", "windows")),
        "plugin_option": anything(),
        "run": one_of((True, False)),
        "secure": one_of(("check", True, False)),
        "src": anything(),
        "timeout_seconds": anything(),
        "uses_polling": anything(),
        "vs_proj_dir": anything(),
        "zlib": one_of((True,)),
    },
    "external_proto_library": {
        "destination": anything(),
        "proto_prefix": anything(),
        "urls": anything(),
        "hash": anything(),
        "strip_prefix": anything(),
    },
}


def check_attributes(entity, kind, errors):
    attributes = VALID_ATTRIBUTE_KEYS_MAP[kind]
    name = entity.get("name", anything())
    for key, value in list(entity.items()):
        if key == "name":
            continue
        validator = attributes.get(key)
        if validator:
            error = validator(value)
            if error:
                errors.append(
                    "{0}({1}) has an invalid value for '{2}': {3}".format(
                        name, kind, key, error
                    )
                )
        else:
            errors.append(
                "{0}({1}) has an invalid attribute '{2}'".format(
                    name, kind, key
                )
            )


def mako_plugin(dictionary):
    """The exported plugin code for check_attr.

    This validates that filegroups, libs, and target can have only valid
    attributes. This is mainly for preventing build.yaml from having
    unnecessary and misleading attributes accidentally.
    """

    errors = []
    for filegroup in dictionary.get("filegroups", {}):
        check_attributes(filegroup, "filegroup", errors)
    for lib in dictionary.get("libs", {}):
        check_attributes(lib, "lib", errors)
    for target in dictionary.get("targets", {}):
        check_attributes(target, "target", errors)
    for target in dictionary.get("external_proto_libraries", {}):
        check_attributes(target, "external_proto_library", errors)
    if errors:
        raise Exception("\n".join(errors))
