# Copyright 2022 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.

"""apple_common.link_multi_arch_static_library Starlark implementation"""

load("@_builtins//:common/objc/compilation_support.bzl", "compilation_support")

CcInfo = _builtins.toplevel.CcInfo
cc_common = _builtins.toplevel.cc_common
apple_common = _builtins.toplevel.apple_common

def _link_multi_arch_static_library(ctx, split_target_triplets = None):
    """Links a (potentially multi-architecture) static library targeting Apple platforms.

    Args:
        ctx: The Starlark rule context.
        split_target_triplets: Dict for split transition keys and target triplet struct (arch,
          platform, environment). These values come from Java (see AppleStarlarkCommon.java) and are
          in place due to no available Starlark API for these values.

          Defaults to None for `apple_static_library` rule usage.

    Returns:
        struct(
            outputs: [
                struct(
                    library: Artifact,
                    architecture: string,
                    platform: string,
                    environment: string,
                )
            ],
            objc: apple_common.Objc,
            output_groups: OutputGroupInfo,
        )
    """
    split_deps = ctx.split_attr.deps
    split_avoid_deps = ctx.split_attr.avoid_deps
    child_configs_and_toolchains = ctx.split_attr._child_configuration_dummy

    outputs = []
    sdk_dylib = []
    sdk_framework = []
    weak_sdk_framework = []

    for split_transition_key, child_toolchain in child_configs_and_toolchains.items():
        cc_toolchain = child_toolchain[cc_common.CcToolchainInfo]
        common_variables = compilation_support.build_common_variables(
            ctx = ctx,
            toolchain = cc_toolchain,
            use_pch = True,
            deps = split_deps[split_transition_key],
        )

        avoid_objc_providers = []
        avoid_cc_providers = []

        if len(split_avoid_deps.keys()):
            for dep in split_avoid_deps[split_transition_key]:
                if apple_common.Objc in dep:
                    avoid_objc_providers.append(dep[apple_common.Objc])
                if CcInfo in dep:
                    avoid_cc_providers.append(dep[CcInfo])

        objc_provider = common_variables.objc_provider.subtract_subtrees(
            avoid_objc_providers = avoid_objc_providers,
            avoid_cc_providers = avoid_cc_providers,
        )

        name = ctx.label.name + "-" + split_transition_key + "-fl"

        linking_outputs = compilation_support.register_fully_link_action(
            common_variables,
            objc_provider,
            name,
        )

        output = {
            "library": linking_outputs.library_to_link.static_library,
        }

        if split_target_triplets != None:
            target_triplet = split_target_triplets.get(split_transition_key)
            output["platform"] = target_triplet.platform
            output["architecture"] = target_triplet.architecture
            output["environment"] = target_triplet.environment

        outputs.append(struct(**output))
        sdk_dylib.append(objc_provider.sdk_dylib)
        sdk_framework.append(objc_provider.sdk_framework)
        weak_sdk_framework.append(objc_provider.weak_sdk_framework)

    objc_provider = apple_common.new_objc_provider(
        sdk_dylib = depset(transitive = sdk_dylib),
        sdk_framework = depset(transitive = sdk_framework),
        weak_sdk_framework = depset(transitive = weak_sdk_framework),
    )

    header_tokens = []
    for _, deps in split_deps.items():
        for dep in deps:
            if CcInfo in dep:
                header_tokens.append(dep[CcInfo].compilation_context.validation_artifacts)

    output_groups = {"_validation": depset(transitive = header_tokens)}

    return struct(
        outputs = outputs,
        objc = objc_provider,
        output_groups = OutputGroupInfo(**output_groups),
    )

linking_support = struct(
    link_multi_arch_static_library = _link_multi_arch_static_library,
)

@@ -1035,24 +1035,120 @@
 platforms.%0A%0A
+    Rule context is a required parameter due to usage of the cc_common.configure_features API.%0A%0A
     Args:%0A  
@@ -1145,16 +1145,16 @@
   Args:%0A
-
         
@@ -1544,38 +1544,62 @@
     
-struct(%0A            outp
+A Starlark struct containing the following attrib
 ut
+e
 s:
- %5B
 %0A   
@@ -1611,63 +1611,176 @@
     
-    struct(%0A                    library: A
+- objc: The Objc provider containing transitive linking information.%0A            - output_groups: OutputGroupInfo provider from transitive CcInfo validation_a
 rtifact
-,%0A    
+s.%0A
     
@@ -1791,130 +1791,238 @@
     
-    architecture: string,%0A                    platform: string,%0A                    environment: string,%0A                )
+- outputs: List of structs containing the following attributes:%0A                - library: Artifact representing a linked static library.%0A                - architecture: Linked static library architecture (e.g. 'arm64', 'x86_64').
 %0A   
@@ -2030,23 +2030,16 @@
     
-    %5D,%0A
         
     
@@ -2038,90 +2038,181 @@
     
-    objc: apple_common.Objc,%0A            output_groups: OutputGroupInfo,%0A        )
+- platform: Linked static library target Apple platform (e.g. 'ios', 'macos').%0A                - environment: Linked static library environment (e.g. 'device', 'simulator').
 %0A   

Improve link_multi_arch_static_library documentation.