# Copyright (C) 2023 The Android Open Source Project
#
# 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.
"""
Export build flags (with values) to make.
"""

load("//build/bazel/utils:schema_validation.scl", "validate")

# Partitions that get build system flag summaries
_flag_partitions = [
    "product",
    "system",
    "system_ext",
    "vendor",
]

ALL = ["all"]
PRODUCT = ["product"]
SYSTEM = ["system"]
SYSTEM_EXT = ["system_ext"]
VENDOR = ["vendor"]

_valid_types = ["NoneType", "bool", "list", "string", "int"]

_all_flags_schema = {
    "type": "list",
    "of": {
        "type": "dict",
        "required_keys": {
            "name": {"type": "string"},
            "partitions": {
                "type": "list",
                "of": {
                    "type": "string",
                    "choices": _flag_partitions + ["all"],
                },
                "unique": True,
            },
            "default": {
                "or": [
                    {"type": t}
                    for t in _valid_types
                ],
            },
            "origin": {"type": "string"},
            "declared_in": {"type": "string"},
        },
        "optional_keys": {
            "appends": {
                "type": "bool",
            },
        },
    },
}

_all_values_schema = {
    "type": "list",
    "of": {
        "type": "dict",
        "required_keys": {
            "name": {"type": "string"},
            "value": {
                "or": [
                    {"type": t}
                    for t in _valid_types
                ],
            },
            "set_in": {"type": "string"},
        },
    },
}

def flag(name, partitions, default, *, origin = "Unknown", appends = False):
    """Declare a flag.

    Args:
      name: name of the flag
      partitions: the partitions where this should be recorded.
      default: the default value of the flag.
      origin: The origin of this flag.
      appends: Whether new values should be append (not replace) the old.

    Returns:
      A dictionary containing the flag declaration.
    """
    if not partitions:
        fail("At least 1 partition is required")
    if not name.startswith("RELEASE_"):
        fail("Release flag names must start with RELEASE_")
    if " " in name or "\t" in name or "\n" in name:
        fail("Flag names must not contain whitespace: \"" + name + "\"")
    for partition in partitions:
        if partition == "all":
            if len(partitions) > 1:
                fail("\"all\" can't be combined with other partitions: " + str(partitions))
        elif partition not in _flag_partitions:
            fail("Invalid partition: " + partition + ", allowed partitions: " +
                 str(_flag_partitions))
    if type(default) not in _valid_types:
        fail("Invalid type of default for flag \"" + name + "\" (" + type(default) + ")")
    return {
        "name": name,
        "partitions": partitions,
        "default": default,
        "appends": appends,
        "origin": origin,
    }

def value(name, value):
    """Define the flag value for a particular configuration.

    Args:
      name: The name of the flag.
      value: The value for the flag.

    Returns:
      A dictionary containing the name and value to be used.
    """
    return {
        "name": name,
        "value": value,
    }

def _format_value(val):
    """Format the starlark type correctly for make.

    Args:
      val: The value to format

    Returns:
      The value, formatted correctly for make.
    """
    if type(val) == "NoneType":
        return ""
    elif type(val) == "bool":
        return "true" if val else ""
    else:
        return val

def equal_flag_declaration(flag, other):
    """Return true if the flag declarations are equal.

    Args:
      flag: This flag declaration.
      other: Another flag declaration.

    Returns:
      Whether the declarations are the same.
    """
    for key in "name", "partitions", "default", "appends":
        if flag[key] != other[key]:
            return False
    # For now, allow Unknown to match any other origin.
    if flag["origin"] == "Unknown" or other["origin"] == "Unknown":
        return True
    return flag["origin"] == other["origin"]

def release_config(all_flags, all_values):
    """Return the make variables that should be set for this release config.

    Args:
      all_flags: A list of flag objects (from flag() calls).
      all_values: A list of value objects (from value() calls).

    Returns:
      A dictionary of {name: value} variables for make.
    """
    validate(all_flags, _all_flags_schema)
    validate(all_values, _all_values_schema)

    # Final values.
    values = {}
    # Validate flags
    flag_names = []
    flags_dict = {}
    for flag in all_flags:
        name = flag["name"]
        if name in flag_names:
            if equal_flag_declaration(flag, flags_dict[name]):
                continue
            else:
                fail(flag["declared_in"] + ": Duplicate declaration of flag " + name +
                     " (declared first in " + flags_dict[name]["declared_in"] + ")")
        flag_names.append(name)
        flags_dict[name] = flag
        # Set the flag value to the default value.
        values[name] = {"name": name, "value": _format_value(flag["default"]), "set_in": flag["declared_in"]}

    # Record which flags go on which partition
    partitions = {}
    for flag in all_flags:
        for partition in flag["partitions"]:
            if partition == "all":
                if len(flag["partitions"]) > 1:
                    fail("\"all\" can't be combined with other partitions: " + str(flag["partitions"]))
                for partition in _flag_partitions:
                    partitions.setdefault(partition, []).append(flag["name"])
            else:
                partitions.setdefault(partition, []).append(flag["name"])

    # Generate final values.
    # Only declared flags may have a value.
    for value in all_values:
        name = value["name"]
        if name not in flag_names:
            fail(value["set_in"] + ": Value set for undeclared build flag: " + name)
        if flags_dict[name]["appends"]:
            if name in values:
                values[name]["value"] += " " + value["value"]
                values[name]["set_in"] += " " + value["set_in"]
            else:
                values[name] = value
        else:
            values[name] = value

    # Collect values
    result = {
        "_ALL_RELEASE_FLAGS": sorted(flag_names),
    }
    for partition, names in partitions.items():
        result["_ALL_RELEASE_FLAGS.PARTITIONS." + partition] = names
    for flag in all_flags:
        val = _format_value(values[flag["name"]]["value"])
        result[flag["name"]] = val
        result["_ALL_RELEASE_FLAGS." + flag["name"] + ".PARTITIONS"] = flag["partitions"]
        result["_ALL_RELEASE_FLAGS." + flag["name"] + ".DEFAULT"] = _format_value(flag["default"])
        result["_ALL_RELEASE_FLAGS." + flag["name"] + ".VALUE"] = val
        result["_ALL_RELEASE_FLAGS." + flag["name"] + ".DECLARED_IN"] = flag["declared_in"]
        result["_ALL_RELEASE_FLAGS." + flag["name"] + ".SET_IN"] = values[flag["name"]]["set_in"]
        result["_ALL_RELEASE_FLAGS." + flag["name"] + ".ORIGIN"] = flag["origin"]

    return result
