// Copyright 2015 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;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ParamFileInfo;
import com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.rules.java.JavaUtil;
import com.google.devtools.build.lib.rules.java.ProguardSpecProvider;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/** Helper class for Android IDL processing. */
public class AndroidIdlHelper {

  /**
   * Name of the output group used for idl jars (the jars containing the class files for sources
   * generated from annotation processors).
   */
  static final String IDL_JARS_OUTPUT_GROUP =
      OutputGroupInfo.HIDDEN_OUTPUT_GROUP_PREFIX + "idl_jars";

  private final RuleContext ruleContext;
  private final AndroidIdlProvider androidIdlProvider;
  private final Map<Artifact, Artifact> translatedIdlSources;
  private final Artifact idlClassJar;
  private final Artifact idlSourceJar;

  /**
   * Creates a new AndroidIdlHelper wrapping the given {@code ruleContext}.
   *
   * @param ruleContext The rule context whose idl attributes will be used to collect .aidl files.
   * @param baseArtifact An artifact used to calculate the paths for the IDL class and source jars.
   */
  public AndroidIdlHelper(RuleContext ruleContext, Artifact baseArtifact) {
    this.ruleContext = ruleContext;

    checkIdlRootImport(ruleContext);

    Collection<Artifact> idls = getIdlSrcs(ruleContext);

    if (!idls.isEmpty() && !ruleContext.hasErrors()) {
      translatedIdlSources = generateTranslatedIdlArtifacts(ruleContext, idls);
      idlClassJar = createIdlJar(baseArtifact, "-idl.jar");
      idlSourceJar = createIdlJar(baseArtifact, "-idl.srcjar");
    } else {
      translatedIdlSources = ImmutableMap.of();
      idlClassJar = null;
      idlSourceJar = null;
    }

    androidIdlProvider = createAndroidIdlProvider(ruleContext, idlClassJar, idlSourceJar);
  }

  /**
   * Adds the necessary providers to the {@code builder}.
   *
   * <p>Adds an {@link AndroidIdlProvider} to the target, and adds the transitive generated IDL jars
   * to the IDL_JARS_OUTPUT_GROUP. This also generates the actions to compile the .aidl files to
   * .java, as well as the .jar and .srcjar files consisting of only the IDL-generated source and
   * class files.
   *
   * @param builder The target builder to add the providers to.
   * @param classJar The class jar to be separated into the IDL class jar.
   * @param manifestProtoOutput The manifest generated by JavaBuilder, for identifying IDL-generated
   *     class files in the class jar.
   */
  public void addTransitiveInfoProviders(
      RuleConfiguredTargetBuilder builder, Artifact classJar, Artifact manifestProtoOutput) {
    if (!translatedIdlSources.isEmpty()) {
      generateAndroidIdlCompilationActions(ruleContext, androidIdlProvider, translatedIdlSources);
      createIdlClassJarAction(
          ruleContext,
          classJar,
          translatedIdlSources.values(),
          manifestProtoOutput,
          idlClassJar,
          idlSourceJar);
    }
    builder
        .addNativeDeclaredProvider(androidIdlProvider)
        .addOutputGroup(IDL_JARS_OUTPUT_GROUP, androidIdlProvider.getTransitiveIdlJars());
  }

  /**
   * Returns the root directory under which idl_srcs and idl_parcelables are located in this rule.
   */
  public String getIdlImportRoot() {
    return hasExplicitlySpecifiedIdlImportRoot(ruleContext) ? getIdlImportRoot(ruleContext) : null;
  }

  /** Returns the raw (non-processed) idl_srcs, not including parcelable marker files. */
  public Collection<Artifact> getIdlSources() {
    return translatedIdlSources.keySet();
  }

  /** Returns the idl_parcelables, consisting of parcelable marker files defined on this rule. */
  public Collection<Artifact> getIdlParcelables() {
    return getIdlParcelables(ruleContext);
  }

  /** Returns the idl_preprocessed. */
  public Collection<Artifact> getIdlPreprocessed() {
    return getIdlPreprocessed(ruleContext);
  }

  /** Returns the generated Java sources created from the idl_srcs. */
  public Collection<Artifact> getIdlGeneratedJavaSources() {
    return translatedIdlSources.values();
  }

  /**
   * Returns the jar containing class files derived from the .aidl files.
   *
   * <p>Will be null if there are no idl_srcs.
   */
  @Nullable
  public Artifact getIdlClassJar() {
    return idlClassJar;
  }

  /**
   * Returns the jar containing source files derived from the .aidl files.
   *
   * <p>Will be null if there are no idl_srcs.
   */
  @Nullable
  public Artifact getIdlSourceJar() {
    return idlSourceJar;
  }

  public static boolean hasIdlSrcs(RuleContext ruleContext) {
    return !getIdlSrcs(ruleContext).isEmpty();
  }

  /**
   * Returns a new list with the idl libs added to the given list if necessary, or the same list.
   */
  public static ImmutableList<TransitiveInfoCollection> maybeAddSupportLibs(
      RuleContext ruleContext, ImmutableList<TransitiveInfoCollection> deps) {
    if (!hasIdlSrcs(ruleContext)) {
      return deps;
    }
    TransitiveInfoCollection aidlLib = AndroidSdkProvider.fromRuleContext(ruleContext).getAidlLib();
    if (aidlLib == null) {
      return deps;
    }
    return ImmutableList.<TransitiveInfoCollection>builder().addAll(deps).add(aidlLib).build();
  }

  public static void maybeAddSupportLibProguardConfigs(
      RuleContext ruleContext, NestedSetBuilder<Artifact> proguardConfigsBuilder) {
    if (!hasIdlSrcs(ruleContext)) {
      return;
    }
    TransitiveInfoCollection aidlLib = AndroidSdkProvider.fromRuleContext(ruleContext).getAidlLib();
    if (aidlLib == null) {
      return;
    }
    ProguardSpecProvider provider = aidlLib.get(ProguardSpecProvider.PROVIDER);
    if (provider == null) {
      return;
    }
    proguardConfigsBuilder.addTransitive(provider.getTransitiveProguardSpecs());
  }

  /** Generates an artifact by replacing the extension of the input with the suffix. */
  private Artifact createIdlJar(Artifact baseArtifact, String suffix) {
    return ruleContext.getDerivedArtifact(
        FileSystemUtils.replaceExtension(baseArtifact.getRootRelativePath(), suffix),
        baseArtifact.getRoot());
  }

  /** Returns the idl_parcelables defined on the given rule. */
  private static ImmutableList<Artifact> getIdlParcelables(RuleContext ruleContext) {
    return ruleContext.getRule().isAttrDefined("idl_parcelables", BuildType.LABEL_LIST)
        ? ImmutableList.copyOf(
            ruleContext
                .getPrerequisiteArtifacts("idl_parcelables", Mode.TARGET)
                .filter(AndroidRuleClasses.ANDROID_IDL)
                .list())
        : ImmutableList.<Artifact>of();
  }

  /** Returns the idl_srcs defined on the given rule. */
  private static Collection<Artifact> getIdlSrcs(RuleContext ruleContext) {
    if (!ruleContext.getRule().isAttrDefined("idl_srcs", BuildType.LABEL_LIST)) {
      return ImmutableList.of();
    }
    checkIdlSrcsSamePackage(ruleContext);
    return ruleContext
        .getPrerequisiteArtifacts("idl_srcs", Mode.TARGET)
        .filter(AndroidRuleClasses.ANDROID_IDL)
        .list();
  }

  /**
   * Checks that all of the idl_srcs in the given rule are in the same package as the rule itself.
   */
  private static void checkIdlSrcsSamePackage(RuleContext ruleContext) {
    PathFragment packageName = ruleContext.getLabel().getPackageFragment();
    Collection<Artifact> idls =
        ruleContext
            .getPrerequisiteArtifacts("idl_srcs", Mode.TARGET)
            .filter(AndroidRuleClasses.ANDROID_IDL)
            .list();
    for (Artifact idl : idls) {
      Label idlLabel = idl.getOwner();
      if (!packageName.equals(idlLabel.getPackageFragment())) {
        ruleContext.attributeError(
            "idl_srcs",
            "do not import '"
                + idlLabel
                + "' directly. "
                + "You should either move the file to this package or depend on "
                + "an appropriate rule there");
      }
    }
  }

  /**
   * Generates matching .java sources for the given .aidl sources.
   *
   * @return A mapping from .aidl input to .java output.
   */
  private static ImmutableMap<Artifact, Artifact> generateTranslatedIdlArtifacts(
      RuleContext ruleContext, Collection<Artifact> idls) {
    ImmutableMap.Builder<Artifact, Artifact> outputJavaSources = ImmutableMap.builder();
    String ruleName = ruleContext.getRule().getName();
    // for each aidl file use aggregated preprocessed files to generate Java code
    for (Artifact idl : idls) {
      // Reconstruct the package tree under <rule>_aidl to avoid a name conflict
      // if the same AIDL files are used in multiple targets.
      PathFragment javaOutputPath =
          FileSystemUtils.replaceExtension(
              PathFragment.create(ruleName + "_aidl").getRelative(idl.getRootRelativePath()),
              ".java");
      Artifact output = ruleContext.getGenfilesArtifact(javaOutputPath.getPathString());
      outputJavaSources.put(idl, output);
    }
    return outputJavaSources.build();
  }

  /**
   * Generates the actions to compile the given .aidl sources into .java sources.
   *
   * @param ruleContext The rule context in which to generate the actions.
   * @param transitiveIdlImportData A provider to supply the artifacts and import roots to give to
   *     the compiler.
   * @param translatedIdlSources A map from input .aidl to output .java of files to be compiled.
   */
  private static void generateAndroidIdlCompilationActions(
      RuleContext ruleContext,
      AndroidIdlProvider transitiveIdlImportData,
      Map<Artifact, Artifact> translatedIdlSources) {
    AndroidSdkProvider sdk = AndroidSdkProvider.fromRuleContext(ruleContext);
    List<String> preprocessedArgs = new ArrayList<>();

    // add import roots so the aidl compiler will know where to look for the imports
    for (String idlImport : transitiveIdlImportData.getTransitiveIdlImportRoots()) {
      preprocessedArgs.add("-I" + idlImport);
    }
    // add preprocessed aidl files
    preprocessedArgs.add("-p" + sdk.getFrameworkAidl().getExecPathString());
    for (Artifact idlPreprocessed : transitiveIdlImportData.getTransitiveIdlPreprocessed()) {
      preprocessedArgs.add("-p" + idlPreprocessed.getExecPathString());
    }

    for (Map.Entry<Artifact, Artifact> entry : translatedIdlSources.entrySet()) {
      createAndroidIdlAction(
          ruleContext,
          entry.getKey(),
          transitiveIdlImportData.getTransitiveIdlImports(),
          entry.getValue(),
          preprocessedArgs);
    }
  }

  /**
   * Creates an action to split out classes and source files created by aidls.
   *
   * @param ruleContext The rule context in which to generate the action.
   * @param classJar The class jar to divide into IDL class and source jars.
   * @param generatedIdlJavaFiles The source files which should be put into the source jar and used
   *     to determine the classes to take.
   * @param manifestProtoOutput The protobuf containing the manifest generated from JavaBuilder.
   * @param idlClassJar The artifact into which the IDL class jar should be written.
   * @param idlSourceJar The artifact into which the IDL source jar should be written.
   */
  private static void createIdlClassJarAction(
      RuleContext ruleContext,
      Artifact classJar,
      Iterable<Artifact> generatedIdlJavaFiles,
      Artifact manifestProtoOutput,
      Artifact idlClassJar,
      Artifact idlSourceJar) {
    String basename = FileSystemUtils.removeExtension(classJar.getExecPath().getBaseName());
    PathFragment idlTempDir =
        ruleContext
            .getConfiguration()
            .getBinDirectory(ruleContext.getRule().getRepository())
            .getExecPath()
            .getRelative(ruleContext.getUniqueDirectory("_idl"))
            .getRelative(basename + "_temp");
    ruleContext.registerAction(
        new SpawnAction.Builder()
            .addInput(manifestProtoOutput)
            .addInput(classJar)
            .addInputs(generatedIdlJavaFiles)
            .addOutput(idlClassJar)
            .addOutput(idlSourceJar)
            .setExecutable(ruleContext.getExecutablePrerequisite("$idlclass", Mode.HOST))
            .addCommandLine(
                CustomCommandLine.builder()
                    .addExecPath("--manifest_proto", manifestProtoOutput)
                    .addExecPath("--class_jar", classJar)
                    .addExecPath("--output_class_jar", idlClassJar)
                    .addExecPath("--output_source_jar", idlSourceJar)
                    .add("--temp_dir")
                    .addPath(idlTempDir)
                    .addExecPaths(ImmutableList.copyOf(generatedIdlJavaFiles))
                    .build(),
                ParamFileInfo.builder(ParameterFileType.SHELL_QUOTED).build())
            .setProgressMessage("Building idl jars %s", idlClassJar.prettyPrint())
            .setMnemonic("AndroidIdlJars")
            .build(ruleContext));
  }

  /**
   * Creates an action to convert an .aidl source into a .java output.
   *
   * @param ruleContext The rule context in which to generate the action.
   * @param idl The .aidl file to be converted to .java.
   * @param idlImports The artifacts which should be accessible to this compilation action.
   * @param output The .java file where the .aidl file will be converted to.
   * @param importArgs The arguments defining the import roots and framework .aidl.
   */
  private static void createAndroidIdlAction(
      RuleContext ruleContext,
      Artifact idl,
      NestedSet<Artifact> idlImports,
      Artifact output,
      List<String> importArgs) {
    AndroidSdkProvider sdk = AndroidSdkProvider.fromRuleContext(ruleContext);
    ruleContext.registerAction(
        new SpawnAction.Builder()
            .setExecutable(sdk.getAidl())
            .addInput(idl)
            .addTransitiveInputs(idlImports)
            .addInput(sdk.getFrameworkAidl())
            .addInputs(getIdlPreprocessed(ruleContext))
            .addOutput(output)
            .setProgressMessage("Android IDL generation")
            .setMnemonic("AndroidIDLGenerate")
            .addCommandLine(
                CustomCommandLine.builder()
                    .add("-b") // Fail if trying to compile a parcelable.
                    .addAll(importArgs)
                    .addExecPath(idl)
                    .addExecPath(output)
                    .build())
            .build(ruleContext));
  }

  /**
   * Returns the union of "idl_srcs" and "idl_parcelables", i.e. all .aidl files provided by this
   * library that contribute to .aidl --> .java compilation.
   */
  private static Collection<Artifact> getIdlImports(RuleContext ruleContext) {
    return ImmutableList.<Artifact>builder()
        .addAll(getIdlParcelables(ruleContext))
        .addAll(getIdlSrcs(ruleContext))
        .addAll(getIdlPreprocessed(ruleContext))
        .build();
  }

  /**
   * Collects the importable .aidl files and AIDL class/source jars from this rule and its deps.
   *
   * @param ruleContext The rule context from which to harvest .aidl sources and parcelables, as
   *     well as dependencies.
   * @param idlClassJar An artifact corresponding to an AIDL class jar for this rule, or null if one
   *     does not exist.
   * @param idlSourceJar An artifact corresponding to an AIDL source jar for this rule, or null if
   *     one does not exist.
   * @return A provider containing the collected data, suitable to be provided by this rule.
   */
  private static AndroidIdlProvider createAndroidIdlProvider(
      RuleContext ruleContext, @Nullable Artifact idlClassJar, @Nullable Artifact idlSourceJar) {
    NestedSetBuilder<String> rootsBuilder = NestedSetBuilder.naiveLinkOrder();
    NestedSetBuilder<Artifact> importsBuilder = NestedSetBuilder.naiveLinkOrder();
    NestedSetBuilder<Artifact> jarsBuilder = NestedSetBuilder.stableOrder();
    NestedSetBuilder<Artifact> preprocessedBuilder = NestedSetBuilder.naiveLinkOrder();
    if (idlClassJar != null) {
      jarsBuilder.add(idlClassJar);
    }
    if (idlSourceJar != null) {
      jarsBuilder.add(idlSourceJar);
    }

    for (AndroidIdlProvider dep :
        AndroidCommon.getTransitivePrerequisites(
            ruleContext, Mode.TARGET, AndroidIdlProvider.PROVIDER)) {
      rootsBuilder.addTransitive(dep.getTransitiveIdlImportRoots());
      importsBuilder.addTransitive(dep.getTransitiveIdlImports());
      preprocessedBuilder.addTransitive(dep.getTransitiveIdlPreprocessed());
      jarsBuilder.addTransitive(dep.getTransitiveIdlJars());
    }

    Collection<Artifact> idlImports = getIdlImports(ruleContext);
    if (!hasExplicitlySpecifiedIdlImportRoot(ruleContext)) {
      for (Artifact idlImport : idlImports) {
        PathFragment javaRoot = JavaUtil.getJavaRoot(idlImport.getExecPath());
        if (javaRoot == null) {
          ruleContext.ruleError(
              "Cannot determine java/javatests root for import " + idlImport.getExecPathString());
        } else {
          rootsBuilder.add(javaRoot.toString());
        }
      }
    } else {
      PathFragment pkgFragment = ruleContext.getLabel().getPackageFragment();
      Set<PathFragment> idlImportRoots = new HashSet<>();
      for (Artifact idlImport : idlImports) {
        idlImportRoots.add(
            idlImport
                .getRoot()
                .getExecPath()
                .getRelative(pkgFragment)
                .getRelative(getIdlImportRoot(ruleContext)));
      }
      for (PathFragment idlImportRoot : idlImportRoots) {
        rootsBuilder.add(idlImportRoot.toString());
      }
    }
    importsBuilder.addAll(idlImports);

    Collection<Artifact> idlPreprocessed = getIdlPreprocessed(ruleContext);
    preprocessedBuilder.addAll(idlPreprocessed);

    return new AndroidIdlProvider(
        rootsBuilder.build(),
        importsBuilder.build(),
        jarsBuilder.build(),
        preprocessedBuilder.build());
  }

  /** Checks that idl_import_root is only set if idl_srcs or idl_parcelables was. */
  private static void checkIdlRootImport(RuleContext ruleContext) {
    if (hasExplicitlySpecifiedIdlImportRoot(ruleContext)
        && !hasExplicitlySpecifiedIdlSrcsOrParcelables(ruleContext)) {
      ruleContext.attributeError(
          "idl_import_root",
          "Neither idl_srcs nor idl_parcelables were specified, "
              + "but 'idl_import_root' attribute was set");
    }
  }

  private static boolean hasExplicitlySpecifiedIdlImportRoot(RuleContext ruleContext) {
    return ruleContext.getRule().isAttributeValueExplicitlySpecified("idl_import_root");
  }

  private static boolean hasExplicitlySpecifiedIdlSrcsOrParcelables(RuleContext ruleContext) {
    return ruleContext.getRule().isAttributeValueExplicitlySpecified("idl_srcs")
        || ruleContext.getRule().isAttributeValueExplicitlySpecified("idl_parcelables");
  }

  private static String getIdlImportRoot(RuleContext ruleContext) {
    return ruleContext.attributes().get("idl_import_root", Type.STRING);
  }

  /** Returns the idl_preprocessed defined on the given rule. */
  private static Collection<Artifact> getIdlPreprocessed(RuleContext ruleContext) {
    return ruleContext.isAttrDefined("idl_preprocessed", BuildType.LABEL_LIST)
        ? ruleContext
            .getPrerequisiteArtifacts("idl_preprocessed", Mode.TARGET)
            .filter(AndroidRuleClasses.ANDROID_IDL)
            .list()
        : ImmutableList.<Artifact>of();
  }
}
