// Copyright 2016 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.
package com.google.devtools.build.lib.rules.android.databinding;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext;
import com.google.devtools.build.lib.analysis.actions.FileWriteAction;
import com.google.devtools.build.lib.analysis.actions.SymlinkAction;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.rules.android.AndroidCommon;
import com.google.devtools.build.lib.rules.android.AndroidConfiguration;
import com.google.devtools.build.lib.rules.android.AndroidDataContext;
import com.google.devtools.build.lib.rules.android.AndroidResources;
import com.google.devtools.build.lib.util.ResourceFileLoader;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.IOException;
import java.util.List;
import javax.annotation.Nullable;

/**
 * Support logic for Bazel's <a
 * href="https://developer.android.com/topic/libraries/data-binding/index.html">data binding</a>
 * integration.
 *
 * <p>In short, data binding in Bazel works as follows:
 *
 * <ol>
 *   <li>If a rule enables data binding and has layout resources with data binding expressions,
 *       resource processing invokes the data binding library to preprocess these expressions, then
 *       strips them out before feeding the resources into aapt. A separate "layout info" XML file
 *       gets produced that contains the bindings.
 *   <li>The data binding annotation processor gets activated on Java compilation. This processor
 *       reads a custom-generated <code>DataBindingInfo.java</code> which specifies the path to the
 *       layout info file (as an annotation). The processor reads that file and produces the
 *       corresponding Java classes that end-user code uses to access the resources.
 *   <li>The data binding compile-time and runtime support libraries get linked into the binary's
 *       deploy jar.
 * </ol>
 *
 * <p>For data binding to work, the corresponding support libraries must be checked into the depot
 * via the implicit dependencies specified inside this class.
 */
public final class DataBinding {

  /** The rule attribute supplying data binding's annotation processor. */
  public static final String DATABINDING_ANNOTATION_PROCESSOR_ATTR =
      "$databinding_annotation_processor";

  /** The rule attribute supplying data binding's build helper (exec). */
  public static final String DATABINDING_EXEC_PROCESSOR_ATTR = "$databinding_exec";

  private static final String ENABLE_DATA_BINDING_ATTR = "enable_data_binding";

  /** The directory where the annotation processor looks for dep metadata. */
  public static final String DEP_METADATA_INPUT_DIR = "dependent-lib-artifacts";

  /** The directory where the annotation processor writes metadata output for the current rule. */
  public static final String METADATA_OUTPUT_DIR = "bin-files";

  @VisibleForTesting
  public static final DataBindingContext DISABLED_V1_CONTEXT = new DisabledDataBindingV1Context();

  private static final DataBindingContext DISABLED_V2_CONTEXT = new DisabledDataBindingV2Context();

  /** Supplies a databinding context from a rulecontext. */
  public static DataBindingContext contextFrom(
      RuleContext ruleContext, AndroidConfiguration androidConfig) {

    return contextFrom(isEnabled(ruleContext), ruleContext, androidConfig);
  }

  /** Supplies a databinding context from an action context. */
  public static DataBindingContext contextFrom(
      boolean enabled, ActionConstructionContext context, AndroidConfiguration androidConfig) {

    if (enabled) {
      if (androidConfig.useDataBindingV2()) {
        return new DataBindingV2Context(context, androidConfig.useDataBindingUpdatedArgs());
      } else {
        return new DataBindingV1Context(context, androidConfig.useDataBindingUpdatedArgs());
      }
    } else {
      if (androidConfig.useDataBindingV2()) {
        return DISABLED_V2_CONTEXT;
      } else {
        return DISABLED_V1_CONTEXT;
      }
    }
  }

  /**
   * Should data binding support be enabled for this rule?
   *
   * <p>Data binding incurs additional resource processing and compilation work as well as
   * additional compile/runtime dependencies. But rules with data binding disabled will fail if data
   * binding expressions appear in their layout resources.
   */
  private static boolean isEnabled(RuleContext ruleContext) {
    return ruleContext.attributes().has(ENABLE_DATA_BINDING_ATTR, Type.BOOLEAN)
        && Boolean.TRUE.equals(
            ruleContext.attributes().get(ENABLE_DATA_BINDING_ATTR, Type.BOOLEAN));
  }

  /** Supplies a disabled (no-op) DataBindingContext. */
  public static DataBindingContext getDisabledDataBindingContext(AndroidDataContext ctx) {
    if (ctx.useDataBindingV2()) {
      return DISABLED_V2_CONTEXT;
    } else {
      return DISABLED_V1_CONTEXT;
    }
  }

  /** Returns this rule's data binding base output dir (as an execroot-relative path). */
  static PathFragment getDataBindingExecPath(RuleContext ruleContext) {
    return ruleContext
        .getBinOrGenfilesDirectory()
        .getExecPath()
        .getRelative(ruleContext.getUniqueDirectory("databinding"));
  }

  static Artifact getLayoutInfoFile(ActionConstructionContext actionConstructionContext) {
    return actionConstructionContext.getUniqueDirectoryArtifact("databinding", "layout-info.zip");
  }

  /** Returns an artifact for the specified output under a standardized data binding base dir. */
  static Artifact getDataBindingArtifact(RuleContext ruleContext, String relativePath) {
    PathFragment binRelativeBasePath =
        getDataBindingExecPath(ruleContext)
            .relativeTo(ruleContext.getBinOrGenfilesDirectory().getExecPath());
    return ruleContext.getDerivedArtifact(
        binRelativeBasePath.getRelative(relativePath), ruleContext.getBinOrGenfilesDirectory());
  }

  static ImmutableList<Artifact> getAnnotationFile(RuleContext ruleContext) {
    // Add this rule's annotation processor input. If the rule doesn't have direct resources,
    // there's no direct data binding info, so there's strictly no need for annotation processing.
    // But it's still important to process the deps' .bin files so any Java class references get
    // re-referenced so they don't get filtered out of the compilation classpath by JavaBuilder
    // (which filters out classpath .jars that "aren't used": see --reduce_classpath). If data
    // binding didn't reprocess a library's data binding expressions redundantly up the dependency
    // chain (meaning each depender processes them again as if they were its own), this problem
    // wouldn't happen.
    try {
      String contents =
          ResourceFileLoader.loadResource(
              DataBinding.class, "databinding_annotation_template.txt");
      Artifact annotationFile = getDataBindingArtifact(ruleContext, "DataBindingInfo.java");
      ruleContext.registerAction(
          FileWriteAction.create(ruleContext, annotationFile, contents, false));
      return ImmutableList.of(annotationFile);
    } catch (IOException e) {
      ruleContext.ruleError("Cannot load annotation processor template: " + e.getMessage());
      return ImmutableList.of();
    }
  }

  /** Returns the data binding resource processing output from deps under the given attribute. */
  static List<Artifact> getTransitiveMetadata(RuleContext ruleContext, String attr) {
    ImmutableList.Builder<Artifact> dataBindingMetadataOutputs = ImmutableList.builder();
    if (ruleContext.attributes().has(attr, BuildType.LABEL_LIST)) {
      for (UsesDataBindingProvider provider :
          ruleContext.getPrerequisites(
              attr, RuleConfiguredTarget.Mode.TARGET, UsesDataBindingProvider.PROVIDER)) {
        dataBindingMetadataOutputs.addAll(provider.getMetadataOutputs());
      }
    }
    return dataBindingMetadataOutputs.build();
  }

  /**
   * Returns metadata outputs from this rule's annotation processing that describe what it did with
   * data binding. This is used by parent rules to ensure consistent binding patterns.
   *
   * <p>>For example, if {@code foo.AndroidBinary} depends on {@code foo.lib.AndroidLibrary} and the
   * library defines data binding expression {@code Bar}, compiling the library produces Java class
   * {@code foo.lib.Bar}. But since the binary applies data binding over the merged resources of its
   * deps, that means the binary also sees {@code Bar}, so it compiles it into {@code foo.Bar}. This
   * would be a class redefinition conflict. But by feeding the library's metadata outputs into the
   * binary's compilation, enough information is available to only use the first version.
   */
  static ImmutableList<Artifact> getMetadataOutputs(
      RuleContext ruleContext, boolean useUpdatedArgs, List<String> metadataOutputSuffixes) {

    if (!AndroidResources.definesAndroidResources(ruleContext.attributes())) {
      // If this rule doesn't define local resources, no resource processing was done, so it
      // doesn't produce data binding output.
      return ImmutableList.of();
    }
    ImmutableList.Builder<Artifact> outputs = ImmutableList.<Artifact>builder();
    String javaPackage = AndroidCommon.getJavaPackage(ruleContext);
    for (String suffix : metadataOutputSuffixes) {
      // The annotation processor automatically creates files with this naming pattern under the
      // {@code -Aandroid.databinding.generationalFileOutDir} base directory.
      if (useUpdatedArgs) {
        outputs.add(
            getDataBindingArtifact(
                ruleContext, String.format("%s/%s-%s", METADATA_OUTPUT_DIR, javaPackage, suffix)));
      } else {
        outputs.add(
            getDataBindingArtifact(
                ruleContext,
                String.format(
                    "%s/%s-%s-%s", METADATA_OUTPUT_DIR, javaPackage, javaPackage, suffix)));
      }
    }
    return outputs.build();
  }

  @Nullable
  static Artifact getMetadataOutput(
      RuleContext ruleContext, boolean useUpdatedArgs, String metadataOutputSuffix) {

    if (!AndroidResources.definesAndroidResources(ruleContext.attributes())) {
      // If this rule doesn't define local resources, no resource processing was done, so it
      // doesn't produce data binding output.
      return null;
    }
    String javaPackage = AndroidCommon.getJavaPackage(ruleContext);

    // The annotation processor automatically creates files with this naming pattern under the
    // {@code -Aandroid.databinding.generationalFileOutDir} base directory.
    if (useUpdatedArgs) {
      return getDataBindingArtifact(
          ruleContext,
          String.format("%s/%s-%s", METADATA_OUTPUT_DIR, javaPackage, metadataOutputSuffix));
    } else {
      return getDataBindingArtifact(
          ruleContext,
          String.format(
              "%s/%s-%s-%s", METADATA_OUTPUT_DIR, javaPackage, javaPackage, metadataOutputSuffix));
    }
  }

  /**
   * Data binding's annotation processor reads the transitive metadata outputs of the target's deps
   * (see {@link #getMetadataOutputs(RuleContext, List<String>)}) in the directory specified by the
   * processor flag {@code -Aandroid.databinding.bindingBuildFolder}. Since dependencies don't
   * generate their outputs under a common directory, we symlink them into a common place here.
   *
   * @return the symlink paths of the transitive dep metadata outputs for this rule
   */
  static Artifact symlinkDepsMetadataIntoOutputTree(RuleContext ruleContext, Artifact depMetadata) {

    Label ruleLabel = ruleContext.getRule().getLabel();
    Artifact symlink =
        getDataBindingArtifact(
            ruleContext,
            String.format(
                "%s/%s", DEP_METADATA_INPUT_DIR, depMetadata.getRootRelativePathString()));
    ruleContext.registerAction(
        SymlinkAction.toArtifact(
            ruleContext.getActionOwner(),
            depMetadata,
            symlink,
            String.format(
                "Symlinking dep metadata output %s for %s", depMetadata.getFilename(), ruleLabel)));
    return symlink;
  }

}
