# Copyright 2018 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.
"""Bazel Android Data Binding."""

load("//providers:providers.bzl", "DataBindingV2Info")
load("//rules:visibility.bzl", "PROJECT_VISIBILITY")
load(":utils.bzl", "ANDROID_TOOLCHAIN_TYPE", _utils = "utils")

visibility(PROJECT_VISIBILITY)

# Data Binding context attributes.
_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS = \
    "java_annotation_processor_additional_inputs"
_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS = \
    "java_annotation_processor_additional_outputs"
_JAVA_PLUGINS = "java_plugins"
_JAVA_SRCS = "java_srcs"
_JAVAC_OPTS = "javac_opts"
_PROVIDERS = "providers"

DataBindingContextInfo = provider(
    doc = "Contains data from processing Android Data Binding.",
    fields = {
        _JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS: (
            "Additional inputs required by the Java annotation processor."
        ),
        _JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS: (
            "Additional outputs produced by the Java annotation processor."
        ),
        _JAVA_PLUGINS: "Data Binding Java annotation processor",
        _JAVA_SRCS: "Java sources required by the Java annotation processor.",
        _JAVAC_OPTS: (
            "Additional Javac opts required by the Java annotation processor."
        ),
        _PROVIDERS: "The list of all providers to propagate.",
    },
)

# Path used when resources have not been defined.
_NO_RESOURCES_PATH = "/tmp/no_resources"

def _copy_annotation_file(ctx, output_dir, annotation_template):
    annotation_out = ctx.actions.declare_file(
        output_dir + "/android/databinding/layouts/DataBindingInfo.java",
    )
    _utils.copy_file(ctx, annotation_template, annotation_out)
    return annotation_out

def _gen_sources(ctx, output_dir, java_package, deps, layout_info, data_binding_exec):
    class_info = ctx.actions.declare_file(output_dir + "class-info.zip")
    srcjar = ctx.actions.declare_file(output_dir + "baseClassSrc.srcjar")

    args = ctx.actions.args()
    args.add("-layoutInfoFiles", layout_info)
    args.add("-package", java_package)
    args.add("-classInfoOut", class_info)
    args.add("-sourceOut", srcjar)
    args.add("-zipSourceOutput", "true")
    args.add("-useAndroidX", "false")

    if deps:
        if type(deps[0].class_infos) == "depset":
            class_infos = depset(transitive = [info.class_infos for info in deps])
            inputs = depset(direct = [layout_info], transitive = [class_infos])
        elif type(deps[0].class_infos) == "list":
            class_infos = []
            for info in deps:
                class_infos.extend(info.class_infos)
            inputs = class_infos + [layout_info]
        else:
            fail("Expected list or depset. Got %s" % type(deps[0].class_infos))
    else:
        class_infos = []
        inputs = [layout_info]

    args.add_all(class_infos, before_each = "-dependencyClassInfoList")

    ctx.actions.run(
        executable = data_binding_exec,
        arguments = ["GEN_BASE_CLASSES", args],
        inputs = inputs,
        outputs = [class_info, srcjar],
        mnemonic = "GenerateDataBindingBaseClasses",
        progress_message = (
            "GenerateDataBindingBaseClasses %s" % class_info.short_path
        ),
        toolchain = ANDROID_TOOLCHAIN_TYPE,
    )
    return srcjar, class_info

def _setup_dependent_lib_artifacts(ctx, output_dir, deps):
    # DataBinding requires files in very specific locations.
    # The following expand_template (copy actions) are moving the files
    # to the correct locations.
    dep_lib_artifacts = []
    for info in deps:
        # Yes, DataBinding requires depsets iterations.
        for artifact in (info.transitive_br_files.to_list() +
                         _utils.list_or_depset_to_list(info.setter_stores) +
                         _utils.list_or_depset_to_list(info.class_infos)):
            # short_path might contain a parent directory reference if the
            # databinding artifact is from an external repository (e.g. an aar
            # from Maven). If that's the case, just remove the parent directory
            # reference, otherwise the "dependent-lib-artifacts" directory will
            # get removed by the "..".
            path = artifact.short_path
            if path.startswith("../"):
                path = path[3:]
            dep_lib_artifact = ctx.actions.declare_file(
                output_dir + "dependent-lib-artifacts/" + path,
            )

            # Copy file to a location required by the DataBinding annotation
            # processor.
            # TODO(djwhang): Look into SymlinkAction.
            if artifact.is_directory:
                _utils.copy_dir(ctx, artifact, dep_lib_artifact)
            else:
                _utils.copy_file(ctx, artifact, dep_lib_artifact)
            dep_lib_artifacts.append(dep_lib_artifact)
    return dep_lib_artifacts

def _get_javac_opts(
        java_package,
        artifact_type,
        dependency_artifacts_dir,
        aar_out_dir,
        class_info_path,
        layout_info_path,
        deps):
    java_packages = []
    for info in deps:
        java_packages.extend(info.java_packages)

    javac_opts = []
    javac_opts.append("-Aandroid.databinding.dependencyArtifactsDir=" +
                      dependency_artifacts_dir)
    javac_opts.append("-Aandroid.databinding.aarOutDir=" + aar_out_dir)
    javac_opts.append("-Aandroid.databinding.sdkDir=/not/used")
    javac_opts.append("-Aandroid.databinding.artifactType=" + artifact_type)
    javac_opts.append("-Aandroid.databinding.exportClassListOutFile=" +
                      "/tmp/exported_classes")
    javac_opts.append("-Aandroid.databinding.modulePackage=" + java_package)
    javac_opts.append("-Aandroid.databinding.directDependencyPkgs=[%s]" %
                      ",".join(java_packages))

    # The minimum Android SDK compatible with this rule.
    # TODO(djwhang): This probably should be based on the actual min-sdk from
    # the manifest, or an appropriate rule attribute.
    javac_opts.append("-Aandroid.databinding.minApi=14")
    javac_opts.append("-Aandroid.databinding.enableV2=1")

    javac_opts.append("-Aandroid.databinding.classLogDir=" + class_info_path)
    javac_opts.append("-Aandroid.databinding.layoutInfoDir=" + layout_info_path)
    return javac_opts

def _merge_lists(lists):
    merged = []
    for sublist in lists:
        merged.extend(sublist)
    return merged

def _process(
        ctx,
        resources_ctx = None,
        defines_resources = False,
        enable_data_binding = False,
        java_package = None,
        layout_info = None,
        artifact_type = "LIBRARY",
        deps = [],
        exports = [],
        data_binding_exec = None,
        data_binding_annotation_processor = None,
        data_binding_annotation_template = None):
    """Processes Android Data Binding.

    Args:
      ctx: The context.
      resources_ctx: The Android Resources context.
      defines_resources: boolean. Determines whether resources were defined.
      enable_data_binding: boolean. Determines whether Data Binding should be
        enabled.
      java_package: String. The Java package.
      layout_info: A file. The layout-info zip file.
      artifact_type: String. Either LIBRARY or APPLICATION.
      deps: sequence of DataBindingV2Info providers. A list of deps. Optional.
      exports: sequence of DataBindingV2Info providers. A list of exports.
        Optional.
      data_binding_exec: The DataBinding executable.
      data_binding_annotation_processor: JavaInfo. The JavaInfo for the
        annotation processor.
      data_binding_annotation_template: A file. Used to generate data binding
        classes.

    Returns:
      A DataBindingContextInfo provider.
    """

    if artifact_type not in ["LIBRARY", "APPLICATION"]:
        fail("Unexpected artifact type: " + artifact_type)

    # TODO(b/154513292): Clean up bad usages of context objects.
    if resources_ctx:
        defines_resources = resources_ctx.defines_resources

    # The Android Data Binding context object.
    db_info = {
        _JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS: [],
        _JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS: [],
        _JAVA_PLUGINS: [],
        _JAVA_SRCS: [],
        _JAVAC_OPTS: [],
        _PROVIDERS: [],
    }

    if not enable_data_binding:
        db_info[_PROVIDERS] = [
            DataBindingV2Info(
                setter_stores = depset(transitive = [info.setter_stores for info in exports]),
                class_infos = depset(transitive = [info.class_infos for info in exports]),
                transitive_br_files = depset(transitive =
                                                 [info.transitive_br_files for info in deps] +
                                                 [info.transitive_br_files for info in exports]),
                java_packages = _merge_lists([info.java_packages for info in exports]),
            ),
        ]
        return struct(**db_info)

    output_dir = "databinding/%s/" % ctx.label.name

    db_info[_JAVA_SRCS].append(_copy_annotation_file(
        ctx,
        output_dir,
        data_binding_annotation_template,
    ))
    db_info[_JAVA_PLUGINS].append(data_binding_annotation_processor)

    br_out = None
    setter_store_out = None
    class_info = None
    if defines_resources:
        # Outputs of the Data Binding annotation processor.
        br_out = ctx.actions.declare_file(
            output_dir + "bin-files/%s-br.bin" % java_package,
        )
        db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS].append(br_out)
        setter_store_out = ctx.actions.declare_file(
            output_dir + "bin-files/%s-setter_store.json" % java_package,
        )
        db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS].append(
            setter_store_out,
        )

        srcjar, class_info = _gen_sources(
            ctx,
            output_dir,
            java_package,
            deps,
            layout_info,
            data_binding_exec,
        )
        db_info[_JAVA_SRCS].append(srcjar)
        db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS].append(class_info)
        db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS].append(
            layout_info,
        )

    dep_lib_artifacts = _setup_dependent_lib_artifacts(ctx, output_dir, deps)
    db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS].extend(
        dep_lib_artifacts,
    )

    db_info[_JAVAC_OPTS] = _get_javac_opts(
        java_package,
        artifact_type,
        (
            br_out.path.rpartition(br_out.short_path)[0] +
            ctx.label.package +
            "/" +
            output_dir +
            "dependent-lib-artifacts"
        ),
        br_out.dirname,
        class_info.path if class_info else _NO_RESOURCES_PATH,
        layout_info.path if layout_info else _NO_RESOURCES_PATH,
        deps,
    )

    db_info[_PROVIDERS] = [
        DataBindingV2Info(
            setter_stores = depset(
                direct = [setter_store_out] if setter_store_out else [],
                transitive = [info.setter_stores for info in exports],
            ),
            class_infos = depset(
                direct = [class_info] if class_info else [],
                transitive = [info.class_infos for info in exports],
            ),
            transitive_br_files = depset(
                direct = [br_out] if br_out else [],
                transitive = [info.transitive_br_files for info in deps] +
                             [info.transitive_br_files for info in exports],
            ),
            java_packages = [java_package] + _merge_lists([info.java_packages for info in exports]),
        ),
    ]

    return DataBindingContextInfo(**db_info)

data_binding = struct(
    process = _process,
)
