// 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.packages.Type;
import com.google.devtools.build.lib.rules.java.JavaUtil;
import com.google.devtools.build.lib.rules.java.ProguardSpecProvider;
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().toList()) {
      preprocessedArgs.add("-I" + idlImport);
    }
    // add preprocessed aidl files
    preprocessedArgs.add("-p" + sdk.getFrameworkAidl().getExecPathString());
    for (Artifact idlPreprocessed :
        transitiveIdlImportData.getTransitiveIdlPreprocessed().toList()) {
      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();
  }
}
