# Copyright 2024 The Bazel Authors. All rights reserved.
#
# 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.
"""Helper functions to allow us to collect data from attr.label_list."""

load(
    "//cc/toolchains:cc_toolchain_info.bzl",
    "ActionTypeConfigSetInfo",
    "ActionTypeSetInfo",
    "ArgsListInfo",
    "FeatureSetInfo",
    "ToolInfo",
)

visibility([
    "//cc/toolchains/...",
    "//tests/rule_based_toolchain/...",
])

def collect_provider(targets, provider):
    """Collects providers from a label list.

    Args:
        targets: (List[Target]) An attribute from attr.label_list
        provider: (provider) The provider to look up
    Returns:
        A list of the providers
    """
    return [target[provider] for target in targets]

def collect_defaultinfo(targets):
    """Collects DefaultInfo from a label list.

    Args:
        targets: (List[Target]) An attribute from attr.label_list
    Returns:
        A list of the associated defaultinfo
    """
    return collect_provider(targets, DefaultInfo)

def _make_collector(provider, field):
    def collector(targets, direct = [], transitive = []):
        # Avoid mutating what was passed in.
        transitive = transitive[:]
        for value in collect_provider(targets, provider):
            transitive.append(getattr(value, field))
        return depset(direct = direct, transitive = transitive)

    return collector

collect_action_types = _make_collector(ActionTypeSetInfo, "actions")
collect_features = _make_collector(FeatureSetInfo, "features")
collect_files = _make_collector(DefaultInfo, "files")

def collect_data(ctx, targets):
    """Collects from a 'data' attribute.

    This is distinguished from collect_files by the fact that data attributes
    attributes include runfiles.

    Args:
        ctx: (Context) The ctx for the current rule
        targets: (List[Target]) A list of files or executables

    Returns:
        A depset containing all files for each of the targets, and all runfiles
        required to run them.
    """
    return ctx.runfiles(transitive_files = collect_files(targets)).merge_all([
        info.default_runfiles
        for info in collect_defaultinfo(targets)
        if info.default_runfiles != None
    ])

def collect_tools(ctx, targets, fail = fail):
    """Collects tools from a label_list.

    Each entry in the label list may either be a cc_tool or a binary.

    Args:
        ctx: (Context) The ctx for the current rule
        targets: (List[Target]) A list of targets. Each of these targets may be
          either a cc_tool or an executable.
        fail: (function) The fail function. Should only be used in tests.

    Returns:
        A List[ToolInfo], with regular executables creating custom tool info.
    """
    tools = []
    for target in targets:
        info = target[DefaultInfo]
        if ToolInfo in target:
            tools.append(target[ToolInfo])
        elif info.files_to_run != None and info.files_to_run.executable != None:
            tools.append(ToolInfo(
                label = target.label,
                exe = info.files_to_run.executable,
                runfiles = collect_data(ctx, [target]),
                requires_any_of = tuple(),
                execution_requirements = tuple(),
            ))
        else:
            fail("Expected %s to be a cc_tool or a binary rule" % target.label)

    return tools

def collect_args_lists(targets, label):
    """Collects a label_list of ArgsListInfo into a single ArgsListInfo

    Args:
        targets: (List[Target]) A label_list of targets providing ArgsListInfo
        label: The label to attach to the resulting ArgsListInfo
    Returns:
        An ArgsListInfo that is the result of joining all of the ArgsListInfos
        together.
    """
    args = []
    by_action = {}
    transitive_files = []
    for target in targets:
        args_list = target[ArgsListInfo]
        args.extend(args_list.args)
        transitive_files.extend([args_info.files for args_info in args_list.args])
        for value in args_list.by_action:
            out = by_action.setdefault(
                value.action,
                struct(args = [], transitive_files = [], action = value.action),
            )
            out.args.extend(value.args)
            out.transitive_files.append(value.files)

    return ArgsListInfo(
        label = label,
        args = tuple(args),
        files = depset(transitive = transitive_files),
        by_action = tuple([
            struct(
                action = k,
                args = tuple(v.args),
                files = depset(transitive = v.transitive_files),
            )
            for k, v in by_action.items()
        ]),
    )

def collect_action_type_config_sets(targets, label, fail = fail):
    """Collects several `cc_action_type_config` labels together.

    Args:
        targets: (List[Target]) A list of targets providing ActionTypeConfigSetInfo
        label: The label to apply to the resulting config.
        fail: (function) The fail function. Should only be used in tests.
    Returns:
        A combined ActionTypeConfigSetInfo representing a variety of action
        types.
    """
    configs = {}
    for atcs in collect_provider(targets, ActionTypeConfigSetInfo):
        for action_type, config in atcs.configs.items():
            if action_type in configs:
                fail("The action type %s is configured by both %s and %s. Each action type may only be configured once." % (action_type.label, config.label, configs[action_type].label))
            configs[action_type] = config
    return ActionTypeConfigSetInfo(label = label, configs = configs)
