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

"""
Common code for reuse across java_* rules
"""

load(":common/rule_util.bzl", "create_composite_dep")
load(":common/java/android_lint.bzl", "android_lint_action")
load(":common/java/compile_action.bzl", "COMPILE_ACTION")
load(":common/java/java_semantics.bzl", "semantics")

java_common = _builtins.toplevel.java_common
coverage_common = _builtins.toplevel.coverage_common

JavaInfo = _builtins.toplevel.JavaInfo
JavaPluginInfo = _builtins.toplevel.JavaPluginInfo
ProtoInfo = _builtins.toplevel.ProtoInfo
CcInfo = _builtins.toplevel.CcInfo

def _filter_srcs(srcs, ext):
    return [f for f in srcs if f.extension == ext]

def _filter_provider(provider, *attrs):
    return [dep[provider] for attr in attrs for dep in attr if provider in dep]

def _get_attr_safe(ctx, attr, default):
    return getattr(ctx.attr, attr) if hasattr(ctx.attr, attr) else default

# TODO(b/11285003): disallow jar files in deps, require java_import instead
def _filter_javainfo_and_legacy_jars(attr):
    dep_list = []

    # Native code collected data into a NestedSet, using add for legacy jars and
    # addTransitive for JavaInfo. This resulted in legacy jars being first in the list.
    for dep in attr:
        kind = java_common.target_kind(dep)
        if not JavaInfo in dep or kind == "java_binary" or kind == "java_test":
            for file in dep[DefaultInfo].files.to_list():
                if file.extension == "jar":
                    # Native doesn't construct JavaInfo
                    java_info = JavaInfo(output_jar = file, compile_jar = file)
                    dep_list.append(java_info)

    for dep in attr:
        if JavaInfo in dep:
            dep_list.append(dep[JavaInfo])
    return dep_list

def basic_java_library(
        ctx,
        srcs,
        deps = [],
        runtime_deps = [],
        plugins = [],
        exports = [],
        exported_plugins = [],
        resources = [],
        classpath_resources = [],
        javacopts = [],
        neverlink = False,
        enable_compile_jar_action = True,
        coverage_config = None):
    """
    Creates actions that compile and lint Java sources, sets up coverage and returns JavaInfo, InstrumentedFilesInfo and output groups.

    The call creates actions and providers needed and shared by `java_library`,
    `java_plugin`,`java_binary`, and `java_test` rules and it is primarily
    intended to be used in those rules.

    To prepare arguments for this call from rule's attributes use the provided
    helpers: `collect_deps`, `collect_plugins`, and `collect_resources`.

    Before compilation coverage.runner is added to the dependencies and if
    present plugins are extended with the value of `--plugin` flag.

    Args:
      ctx: (RuleContext) Used to register the actions.
      srcs: (list[File]) The list of source files that are processed to create the target.
      deps: (list[Target]) The list of other libraries to be linked in to the target.
      runtime_deps: (list[Target]) Libraries to make available to the final binary or test at runtime only.
      plugins: (list[Target]) Java compiler plugins to run at compile-time.
      exports: (list[Target]) Exported libraries.
      exported_plugins: (list[Target]) The list of `java_plugin`s (e.g. annotation
        processors) to export to libraries that directly depend on this library.
      resources: (list[File]) A list of data files to include in a Java jar.
      classpath_resources: (list[File])
      javacopts: (list[str])
      neverlink: (bool) Whether this library should only be used for compilation and not at runtime.
      enable_compile_jar_action: (bool) Enables header compilation or ijar creation.
      coverage_config: (struct{runner:Target, support_files:list[File]|depset[File], env:dict[str,str]})
        Coverage configuration. `runner` is added to dependencies during
        compilation, `support_files` and `env` is returned in InstrumentedFilesInfo.

    Returns:
      ({java_info: JavaInfo,
        files_to_build: list[File],
        has_sources_or_resources: bool,
        instrumented_files_info: InstrumentedFilesInfo,
        output_groups: dict[str,list[File]],
        extra_providers: list[Provider]})
    """
    source_files = _filter_srcs(srcs, "java")
    source_jars = _filter_srcs(srcs, "srcjar")

    java_info, compilation_info = COMPILE_ACTION.call(
        ctx,
        output_class_jar = ctx.outputs.classjar,
        output_source_jar = ctx.outputs.sourcejar,
        source_files = source_files,
        source_jars = source_jars,
        deps = _collect_deps(deps + ([coverage_config.runner] if coverage_config else [])),
        runtime_deps = _collect_deps(runtime_deps),
        plugins = _collect_plugins(plugins + [ctx.attr._java_plugins]),
        exports = _collect_deps(exports),
        exported_plugins = _collect_plugins(exported_plugins),
        resources = resources + _filter_srcs(srcs, "properties"),
        classpath_resources = classpath_resources,
        native_libraries = _collect_native_libraries(deps, runtime_deps, exports),
        javacopts = javacopts,
        neverlink = neverlink,
        strict_deps = ctx.fragments.java.strict_java_deps,
        enable_compile_jar_action = enable_compile_jar_action,
    )

    output_groups = dict(
        compilation_outputs = compilation_info.output_class_jars,
        _source_jars = java_info.transitive_source_jars,
        _direct_source_jars = java_info.source_jars,
    )

    # TODO(b/131760365): This is a hack, since the Starlark APIs don't have
    # an explicit test for "host" or "tool" configuration.
    if not (ctx.configuration == ctx.host_configuration or
            ctx.bin_dir.path.find("-exec-") >= 0) and not neverlink:
        lint_output = android_lint_action(
            ctx,
            source_files,
            source_jars + [output.generated_source_jar for output in java_info.java_outputs if output.generated_source_jar != None],
            compilation_info,
        )
        if lint_output:
            output_groups["_validation"] = [lint_output]

    instrumented_files_info = coverage_common.instrumented_files_info(
        ctx,
        source_attributes = ["srcs"],
        dependency_attributes = ["deps", "data", "resources", "resource_jars", "exports", "runtime_deps", "jars"],
        coverage_support_files = coverage_config.support_files if coverage_config else depset(),
        coverage_environment = coverage_config.env if coverage_config else {},
    )

    return struct(
        java_info = java_info,
        files_to_build = compilation_info.output_class_jars,
        has_sources_or_resources = source_files or source_jars or resources,
        instrumented_files_info = instrumented_files_info,
        output_groups = output_groups,
        extra_providers = {},
    )

def collect_resources(ctx, extra_resources = []):
    """Collects resources files from different attributes defined by Java rules.

    The default location to specify resources is resources attribute.

    .properties files may be also specified in srcs attribute.

    Depending on semantics proto_library targets in resources attribute may be
    expanded to .proto files or to a descriptor set.

    Args:
      ctx: (RuleContext) Uses ctx.attr.resources, ctx.files.resources, ctx.files.srcs.
      extra_resources: (list[File]) Additional resource files.
    Returns:
      (list[File]) List of resource files.
    """
    resources = []
    if semantics.COLLECT_SRCS_FROM_PROTO_LIBRARY:
        for resource in ctx.attr.resources:
            if ProtoInfo in resource:
                resources.extend(resource[ProtoInfo].transitive_sources.to_list())
            else:
                resources.extend(resource[DefaultInfo].files.to_list())
    else:
        resources.extend(ctx.files.resources)
    resources.extend(extra_resources)
    return resources

def _collect_plugins(plugins):
    """Collects plugins from an attribute.

    Use this call to collect plugins from `plugins` or `exported_plugins` attribute.

    The call simply extracts JavaPluginInfo provider.

    Args:
      plugins: (list[Target]) Attribute to collect plugins from.
    Returns:
      (list[JavaPluginInfo]) The plugins.
    """
    return _filter_provider(JavaPluginInfo, plugins)

def _collect_deps(deps):
    """Collects dependencies from an attribute.

    Use this call to collect plugins from `deps`, `runtime_deps`, or `exports` attribute.

    The call extracts JavaInfo and additionaly also "legacy jars". "legacy jars"
    are wrapped into a JavaInfo.

    Args:
      deps: (list[Target]) Attribute to collect dependencies from.
    Returns:
      (list[JavaInfo]) The dependencies.
    """
    return _filter_javainfo_and_legacy_jars(deps)

def _collect_native_libraries(*attrs):
    """Collects native libraries from a list of attributes.

    Use this call to collect native libraries from `deps`, `runtime_deps`, or `exports` attributes.

    The call simply extracts CcInfo provider.
    Args:
      *attrs: (*list[Target]) Attribute to collect native libraries from.
    Returns:
      (list[CcInfo]) The native library dependencies.
    """
    return _filter_provider(CcInfo, *attrs)

def construct_defaultinfo(ctx, files, neverlink, has_sources_or_resources, *extra_attrs):
    """Constructs DefaultInfo for Java library like rule.

    Args:
      ctx: (RuleContext) Used to construct the runfiles.
      files: (list[File]) List of the files built by the rule.
      neverlink: (bool) When true empty runfiles are constructed.
      has_sources_or_resources: (bool) TODO(b/213551463): Check if this can be removed.
      *extra_attrs: (list[Target]) Extra attributes to merge runfiles from.

    Returns:
      (DefaultInfo) DefaultInfo provider.
    """
    files_depset = depset(files)
    if neverlink:
        runfiles = None
    else:
        run_files = files_depset if has_sources_or_resources else None
        runfiles = ctx.runfiles(transitive_files = run_files, collect_default = True)
        runfiles = runfiles.merge_all([dep[DefaultInfo].default_runfiles for attr in extra_attrs for dep in attr])
    default_info = DefaultInfo(
        files = files_depset,
        runfiles = runfiles,
    )
    return default_info

JAVA_COMMON_DEP = create_composite_dep(
    basic_java_library,
    COMPILE_ACTION,
)
