/*
 * Copyright 2013-present Facebook, Inc.
 *
 * 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.facebook.buck.android;

import com.facebook.buck.android.AndroidBinary.ExopackageMode;
import com.facebook.buck.android.AndroidBinary.PackageType;
import com.facebook.buck.android.AndroidBinary.TargetCpuType;
import com.facebook.buck.android.FilterResourcesStep.ResourceFilter;
import com.facebook.buck.android.ResourcesFilter.ResourceCompressionMode;
import com.facebook.buck.cxx.CxxPlatform;
import com.facebook.buck.java.JavaLibrary;
import com.facebook.buck.java.JavaNativeLinkable;
import com.facebook.buck.java.JavacOptions;
import com.facebook.buck.java.Keystore;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.Flavor;
import com.facebook.buck.model.HasBuildTarget;
import com.facebook.buck.model.ImmutableFlavor;
import com.facebook.buck.model.Pair;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.BuildRules;
import com.facebook.buck.rules.PathSourcePath;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.coercer.BuildConfigFields;
import com.facebook.buck.rules.coercer.ImmutableBuildConfigFields;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Suppliers;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;

import java.nio.file.Path;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Map;

public class AndroidBinaryGraphEnhancer {

  private static final Flavor COPY_NATIVE_LIBS_FLAVOR = ImmutableFlavor.of("copy_native_libs");
  private static final Flavor DEX_FLAVOR = ImmutableFlavor.of("dex");
  private static final Flavor DEX_MERGE_FLAVOR = ImmutableFlavor.of("dex_merge");
  private static final Flavor RESOURCES_FILTER_FLAVOR = ImmutableFlavor.of("resources_filter");
  private static final Flavor AAPT_PACKAGE_FLAVOR = ImmutableFlavor.of("aapt_package");
  private static final Flavor CALCULATE_ABI_FLAVOR = ImmutableFlavor.of("calculate_exopackage_abi");
  private static final Flavor PACKAGE_STRING_ASSETS_FLAVOR =
      ImmutableFlavor.of("package_string_assets");

  private final BuildTarget originalBuildTarget;
  private final ImmutableSortedSet<BuildRule> originalDeps;
  private final BuildRuleParams buildRuleParams;
  private final BuildRuleResolver ruleResolver;
  private final SourcePathResolver pathResolver;
  private final ResourceCompressionMode resourceCompressionMode;
  private final ResourceFilter resourceFilter;
  private final ImmutableSet<String> locales;
  private final SourcePath manifest;
  private final PackageType packageType;
  private final ImmutableSet<TargetCpuType> cpuFilters;
  private final boolean shouldBuildStringSourceMap;
  private final boolean shouldPreDex;
  private final Path primaryDexPath;
  private final DexSplitMode dexSplitMode;
  private final ImmutableSet<BuildTarget> buildTargetsToExcludeFromDex;
  private final ImmutableSet<BuildTarget> resourcesToExclude;
  private final boolean skipCrunchPngs;
  private final JavacOptions javacOptions;
  private final EnumSet<ExopackageMode> exopackageModes;
  private final Keystore keystore;
  private final BuildConfigFields buildConfigValues;
  private final Optional<SourcePath> buildConfigValuesFile;

  /**
   * Maps a {@link TargetCpuType} to the {@link CxxPlatform} we need to use to build C/C++
   * libraries for it.
   */
  private final ImmutableMap<TargetCpuType, NdkCxxPlatform> nativePlatforms;

  AndroidBinaryGraphEnhancer(
      BuildRuleParams originalParams,
      BuildRuleResolver ruleResolver,
      ResourceCompressionMode resourceCompressionMode,
      ResourceFilter resourcesFilter,
      ImmutableSet<String> locales,
      SourcePath manifest,
      PackageType packageType,
      ImmutableSet<TargetCpuType> cpuFilters,
      boolean shouldBuildStringSourceMap,
      boolean shouldPreDex,
      Path primaryDexPath,
      DexSplitMode dexSplitMode,
      ImmutableSet<BuildTarget> buildTargetsToExcludeFromDex,
      ImmutableSet<BuildTarget> resourcesToExclude,
      boolean skipCrunchPngs,
      JavacOptions javacOptions,
      EnumSet<ExopackageMode> exopackageModes,
      Keystore keystore,
      BuildConfigFields buildConfigValues,
      Optional<SourcePath> buildConfigValuesFile,
      ImmutableMap<TargetCpuType, NdkCxxPlatform> nativePlatforms) {
    this.buildRuleParams = originalParams;
    this.originalBuildTarget = originalParams.getBuildTarget();
    this.originalDeps = originalParams.getDeps();
    this.ruleResolver = ruleResolver;
    this.pathResolver = new SourcePathResolver(ruleResolver);
    this.resourceCompressionMode = resourceCompressionMode;
    this.resourceFilter = resourcesFilter;
    this.locales = locales;
    this.manifest = manifest;
    this.packageType = packageType;
    this.cpuFilters = cpuFilters;
    this.shouldBuildStringSourceMap = shouldBuildStringSourceMap;
    this.shouldPreDex = shouldPreDex;
    this.primaryDexPath = primaryDexPath;
    this.dexSplitMode = dexSplitMode;
    this.buildTargetsToExcludeFromDex = buildTargetsToExcludeFromDex;
    this.resourcesToExclude = resourcesToExclude;
    this.skipCrunchPngs = skipCrunchPngs;
    this.javacOptions = javacOptions;
    this.exopackageModes = exopackageModes;
    this.keystore = keystore;
    this.buildConfigValues = buildConfigValues;
    this.buildConfigValuesFile = buildConfigValuesFile;
    this.nativePlatforms = nativePlatforms;
  }

  AndroidGraphEnhancementResult createAdditionalBuildables() {
    ImmutableSortedSet.Builder<BuildRule> enhancedDeps = ImmutableSortedSet.naturalOrder();
    enhancedDeps.addAll(originalDeps);

    AndroidPackageableCollector collector =
        new AndroidPackageableCollector(
            originalBuildTarget,
            buildTargetsToExcludeFromDex,
            resourcesToExclude);
    collector.addPackageables(AndroidPackageableCollector.getPackageableRules(originalDeps));
    ImmutableAndroidPackageableCollection packageableCollection = collector.build();
    AndroidPackageableCollection.ResourceDetails resourceDetails =
        packageableCollection.getResourceDetails();

    ImmutableSortedSet<BuildRule> resourceRules =
        getTargetsAsRules(resourceDetails.getResourcesWithNonEmptyResDir());

    FilteredResourcesProvider filteredResourcesProvider;
    boolean needsResourceFiltering = resourceFilter.isEnabled() ||
        resourceCompressionMode.isStoreStringsAsAssets() ||
        !locales.isEmpty();

    if (needsResourceFiltering) {
      BuildRuleParams paramsForResourcesFilter = buildRuleParams.copyWithChanges(
          BuildRuleType.RESOURCES_FILTER,
          createBuildTargetWithFlavor(RESOURCES_FILTER_FLAVOR),
          Suppliers.ofInstance(resourceRules),
          /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()));
      ResourcesFilter resourcesFilter = new ResourcesFilter(
          paramsForResourcesFilter,
          pathResolver,
          resourceDetails.getResourceDirectories(),
          ImmutableSet.copyOf(resourceDetails.getWhitelistedStringDirectories()),
          locales,
          resourceCompressionMode,
          resourceFilter);
      ruleResolver.addToIndex(resourcesFilter);

      filteredResourcesProvider = resourcesFilter;
      enhancedDeps.add(resourcesFilter);
      resourceRules = ImmutableSortedSet.<BuildRule>of(resourcesFilter);
    } else {
      filteredResourcesProvider =
          new IdentityResourcesProvider(resourceDetails.getResourceDirectories());
    }

    // Create the AaptPackageResourcesBuildable.
    BuildTarget buildTargetForAapt = createBuildTargetWithFlavor(AAPT_PACKAGE_FLAVOR);
    BuildRuleParams paramsForAaptPackageResources = buildRuleParams.copyWithChanges(
        BuildRuleType.AAPT_PACKAGE,
        buildTargetForAapt,
        Suppliers.ofInstance(
            getAdditionalAaptDeps(pathResolver, resourceRules, packageableCollection)),
        /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()));
    AaptPackageResources aaptPackageResources = new AaptPackageResources(
        paramsForAaptPackageResources,
        pathResolver,
        manifest,
        filteredResourcesProvider,
        getTargetsAsResourceDeps(resourceDetails.getResourcesWithNonEmptyResDir()),
        packageableCollection.getAssetsDirectories(),
        packageType,
        cpuFilters,
        javacOptions,
        shouldPreDex,
        shouldBuildStringSourceMap,
        locales.isEmpty(),
        skipCrunchPngs);
    ruleResolver.addToIndex(aaptPackageResources);
    enhancedDeps.add(aaptPackageResources);

    Optional<PackageStringAssets> packageStringAssets = Optional.absent();
    if (resourceCompressionMode.isStoreStringsAsAssets()) {
      BuildTarget buildTargetForPackageStringAssets =
          createBuildTargetWithFlavor(PACKAGE_STRING_ASSETS_FLAVOR);
      BuildRuleParams paramsForPackageStringAssets = buildRuleParams.copyWithChanges(
          BuildRuleType.PACKAGE_STRING_ASSETS,
          buildTargetForPackageStringAssets,
          Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of(aaptPackageResources)),
          /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()));
      packageStringAssets = Optional.of(
          new PackageStringAssets(
              paramsForPackageStringAssets,
              pathResolver,
              filteredResourcesProvider,
              aaptPackageResources));
      ruleResolver.addToIndex(packageStringAssets.get());
      enhancedDeps.add(packageStringAssets.get());
    }

    // TODO(natthu): Try to avoid re-building the collection by passing UberRDotJava directly.
    if (packageableCollection.getResourceDetails().hasResources()) {
      collector.addClasspathEntry(
          aaptPackageResources,
          aaptPackageResources.getPathToCompiledRDotJavaFiles());
    }

    // BuildConfig deps should not be added for instrumented APKs because BuildConfig.class has
    // already been added to the APK under test.
    ImmutableList<DexProducedFromJavaLibrary> preDexBuildConfigs;
    ImmutableList<Path> buildConfigJarFiles;
    if (packageType == PackageType.INSTRUMENTED) {
      preDexBuildConfigs = ImmutableList.of();
      buildConfigJarFiles = ImmutableList.of();
    } else {
      ImmutableList.Builder<DexProducedFromJavaLibrary> preDexBuildConfigsBuilder =
          ImmutableList.builder();
      ImmutableList.Builder<Path> buildConfigJarFilesBuilder = ImmutableList.builder();
      addBuildConfigDeps(
          shouldPreDex,
          packageableCollection,
          enhancedDeps,
          preDexBuildConfigsBuilder,
          buildConfigJarFilesBuilder);
      preDexBuildConfigs = preDexBuildConfigsBuilder.build();
      buildConfigJarFiles = buildConfigJarFilesBuilder.build();
    }

    packageableCollection = collector.build();

    Optional<PreDexMerge> preDexMerge = Optional.absent();
    if (shouldPreDex) {
      preDexMerge = Optional.of(createPreDexMergeRule(
              aaptPackageResources,
              preDexBuildConfigs,
              packageableCollection));
      enhancedDeps.add(preDexMerge.get());
    } else {
      enhancedDeps.addAll(getTargetsAsRules(packageableCollection.getJavaLibrariesToDex()));
    }

    // Iterate over all the {@link AndroidNativeLinkable}s from the collector and grab the shared
    // libraries for all the {@link TargetCpuType}s that we care about.  We deposit them into a map
    // of CPU type and SONAME to the shared library path, which the {@link CopyNativeLibraries}
    // rule will use to compose the destination name.
    ImmutableMap.Builder<Pair<TargetCpuType, String>, SourcePath> nativeLinkableLibsBuilder =
        ImmutableMap.builder();

    // TODO(agallagher): We currently treat an empty set of filters to mean to allow everything.
    // We should fix this by assigning a default list of CPU filters in the descriptions, but
    // until we doIf the set of filters is empty, just build for all available platforms.
    ImmutableSet<TargetCpuType> filters =
        cpuFilters.isEmpty() ? nativePlatforms.keySet() : cpuFilters;
    for (TargetCpuType targetCpuType : filters) {
      NdkCxxPlatform platform = Preconditions.checkNotNull(nativePlatforms.get(targetCpuType));

      for (JavaNativeLinkable nativeLinkable : packageableCollection.getNativeLinkables()) {
        ImmutableMap<String, SourcePath> solibs = nativeLinkable.getSharedLibraries(
            platform.getCxxPlatform());
        for (Map.Entry<String, SourcePath> entry : solibs.entrySet()) {
          nativeLinkableLibsBuilder.put(
              new Pair<>(targetCpuType, entry.getKey()),
              entry.getValue());
        }
      }

      // If we're using a C/C++ runtime other than the system one, add it to the APK.
      NdkCxxPlatforms.CxxRuntime cxxRuntime = platform.getCxxRuntime();
      if (!packageableCollection.getNativeLinkables().isEmpty() &&
          !cxxRuntime.equals(NdkCxxPlatforms.CxxRuntime.SYSTEM)) {
        nativeLinkableLibsBuilder.put(
            new Pair<>(
                targetCpuType,
                cxxRuntime.getSoname()),
            new PathSourcePath(
                buildRuleParams.getProjectFilesystem(),
                platform.getCxxSharedRuntimePath()));
      }
    }
    ImmutableMap<Pair<TargetCpuType, String>, SourcePath> nativeLinkableLibs =
        nativeLinkableLibsBuilder.build();

    Optional<CopyNativeLibraries> copyNativeLibraries = Optional.absent();
    if (!packageableCollection.getNativeLibsDirectories().isEmpty() ||
        !nativeLinkableLibs.isEmpty()) {
      BuildRuleParams paramsForCopyNativeLibraries = buildRuleParams.copyWithChanges(
          BuildRuleType.COPY_NATIVE_LIBS,
          createBuildTargetWithFlavor(COPY_NATIVE_LIBS_FLAVOR),
          Suppliers.ofInstance(
              ImmutableSortedSet.<BuildRule>naturalOrder()
                  .addAll(getTargetsAsRules(packageableCollection.getNativeLibsTargets()))
                  .addAll(pathResolver.filterBuildRuleInputs(nativeLinkableLibs.values()))
                  .build()),
          /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()));
      copyNativeLibraries = Optional.of(
          new CopyNativeLibraries(
              paramsForCopyNativeLibraries,
              pathResolver,
              packageableCollection.getNativeLibsDirectories(),
              cpuFilters,
              nativePlatforms,
              nativeLinkableLibs));
      ruleResolver.addToIndex(copyNativeLibraries.get());
      enhancedDeps.add(copyNativeLibraries.get());
    }

    ImmutableSortedSet<BuildRule> finalDeps;
    Optional<ComputeExopackageDepsAbi> computeExopackageDepsAbi = Optional.absent();
    if (!exopackageModes.isEmpty()) {
      BuildRuleParams paramsForComputeExopackageAbi = buildRuleParams.copyWithChanges(
          BuildRuleType.EXOPACKAGE_DEPS_ABI,
          createBuildTargetWithFlavor(CALCULATE_ABI_FLAVOR),
          Suppliers.ofInstance(enhancedDeps.build()),
          /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()));
      computeExopackageDepsAbi = Optional.of(
          new ComputeExopackageDepsAbi(
              paramsForComputeExopackageAbi,
              pathResolver,
              exopackageModes,
              packageableCollection,
              aaptPackageResources,
              copyNativeLibraries,
              packageStringAssets,
              preDexMerge,
              keystore));
      ruleResolver.addToIndex(computeExopackageDepsAbi.get());
      finalDeps = ImmutableSortedSet.<BuildRule>of(computeExopackageDepsAbi.get());
    } else {
      finalDeps = enhancedDeps.build();
    }

    return ImmutableAndroidGraphEnhancementResult.builder()
        .setPackageableCollection(packageableCollection)
        .setAaptPackageResources(aaptPackageResources)
        .setCopyNativeLibraries(copyNativeLibraries)
        .setPackageStringAssets(packageStringAssets)
        .setPreDexMerge(preDexMerge)
        .setComputeExopackageDepsAbi(computeExopackageDepsAbi)
        .setClasspathEntriesToDex(ImmutableSet.<Path>builder()
            .addAll(packageableCollection.getClasspathEntriesToDex())
            .addAll(buildConfigJarFiles)
            .build())
        .setFinalDeps(finalDeps)
        .build();
  }

  /**
   * If the user specified any android_build_config() rules, then we must add some build rules to
   * generate the production {@code BuildConfig.class} files and ensure that they are included in
   * the list of {@link AndroidPackageableCollection#getClasspathEntriesToDex}.
   */
  private void addBuildConfigDeps(
      boolean shouldPreDex,
      AndroidPackageableCollection packageableCollection,
      ImmutableSortedSet.Builder<BuildRule> enhancedDeps,
      ImmutableList.Builder<DexProducedFromJavaLibrary> preDexRules,
      ImmutableList.Builder<Path> buildConfigJarFilesBuilder) {
    BuildConfigFields buildConfigConstants = BuildConfigFields.fromFields(
        ImmutableList.<BuildConfigFields.Field>of(
            ImmutableBuildConfigFields.Field.of(
                "boolean",
                BuildConfigs.DEBUG_CONSTANT,
                String.valueOf(packageType != AndroidBinary.PackageType.RELEASE)),
            ImmutableBuildConfigFields.Field.of(
                "boolean",
                BuildConfigs.IS_EXO_CONSTANT,
                String.valueOf(!exopackageModes.isEmpty())),
            ImmutableBuildConfigFields.Field.of(
                "int",
                BuildConfigs.EXOPACKAGE_FLAGS,
                String.valueOf(ExopackageMode.toBitmask(exopackageModes)))));
    for (Map.Entry<String, BuildConfigFields> entry :
        packageableCollection.getBuildConfigs().entrySet()) {
      // Merge the user-defined constants with the APK-specific overrides.
      BuildConfigFields totalBuildConfigValues = BuildConfigFields.empty()
          .putAll(entry.getValue())
          .putAll(buildConfigValues)
          .putAll(buildConfigConstants);

      // Each enhanced dep needs a unique build target, so we parameterize the build target by the
      // Java package.
      String javaPackage = entry.getKey();
      Flavor flavor = ImmutableFlavor.of("buildconfig_" + javaPackage.replace('.', '_'));
      BuildRuleParams buildConfigParams = new BuildRuleParams(
          createBuildTargetWithFlavor(flavor),
          /* declaredDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()),
          /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()),
          buildRuleParams.getProjectFilesystem(),
          buildRuleParams.getRuleKeyBuilderFactory(),
          AndroidBuildConfigDescription.TYPE,
          buildRuleParams.getTargetGraph());
      JavaLibrary buildConfigJavaLibrary = AndroidBuildConfigDescription.createBuildRule(
          buildConfigParams,
          javaPackage,
          totalBuildConfigValues,
          buildConfigValuesFile,
          /* useConstantExpressions */ true,
          javacOptions,
          ruleResolver);
      ruleResolver.addToIndex(buildConfigJavaLibrary);

      enhancedDeps.add(buildConfigJavaLibrary);
      Path buildConfigJar = buildConfigJavaLibrary.getPathToOutputFile();
      Preconditions.checkNotNull(
          buildConfigJar,
          "%s must have an output file.",
          buildConfigJavaLibrary);
      buildConfigJarFilesBuilder.add(buildConfigJar);

      if (shouldPreDex) {
        DexProducedFromJavaLibrary buildConfigDex = new DexProducedFromJavaLibrary(
            buildConfigParams.copyWithChanges(
                BuildRuleType.PRE_DEX,
                createBuildTargetWithFlavor(ImmutableFlavor.of("dex_" + flavor.getName())),
                Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of(buildConfigJavaLibrary)),
                /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())),
            pathResolver,
            buildConfigJavaLibrary);
        ruleResolver.addToIndex(buildConfigDex);
        enhancedDeps.add(buildConfigDex);
        preDexRules.add(buildConfigDex);
      }
    }
  }

  /**
   * Creates/finds the set of build rules that correspond to pre-dex'd artifacts that should be
   * merged to create the final classes.dex for the APK.
   * <p>
   * This method may modify {@code ruleResolver}, inserting new rules into its index.
   */
  @VisibleForTesting
  PreDexMerge createPreDexMergeRule(
      AaptPackageResources aaptPackageResources,
      Iterable<DexProducedFromJavaLibrary> preDexRulesNotInThePackageableCollection,
      AndroidPackageableCollection packageableCollection) {
    ImmutableSet.Builder<DexProducedFromJavaLibrary> preDexDeps = ImmutableSet.builder();
    preDexDeps.addAll(preDexRulesNotInThePackageableCollection);
    for (BuildTarget buildTarget : packageableCollection.getJavaLibrariesToDex()) {
      Preconditions.checkState(
          !buildTargetsToExcludeFromDex.contains(buildTarget),
          "JavaLibrary should have been excluded from target to dex: %s", buildTarget);

      BuildRule libraryRule = ruleResolver.getRule(buildTarget);

      // Skip uber R.java since AaptPackageResources takes care of dexing.
      if (libraryRule.equals(aaptPackageResources)) {
        continue;
      }

      Preconditions.checkState(libraryRule instanceof JavaLibrary);
      JavaLibrary javaLibrary = (JavaLibrary) libraryRule;

      // If the rule has no output file (which happens when a java_library has no srcs or
      // resources, but export_deps is true), then there will not be anything to dx.
      if (javaLibrary.getPathToOutputFile() == null) {
        continue;
      }

      // See whether the corresponding IntermediateDexRule has already been added to the
      // ruleResolver.
      BuildTarget originalTarget = javaLibrary.getBuildTarget();
      BuildTarget preDexTarget = BuildTarget.builder(originalTarget)
          .addFlavors(DEX_FLAVOR)
          .build();
      Optional<BuildRule> preDexRule = ruleResolver.getRuleOptional(preDexTarget);
      if (preDexRule.isPresent()) {
        preDexDeps.add((DexProducedFromJavaLibrary) preDexRule.get());
        continue;
      }

      // Create the IntermediateDexRule and add it to both the ruleResolver and preDexDeps.
      BuildRuleParams paramsForPreDex = buildRuleParams.copyWithChanges(
          BuildRuleType.PRE_DEX,
          preDexTarget,
          Suppliers.ofInstance(
              ImmutableSortedSet.of(ruleResolver.getRule(javaLibrary.getBuildTarget()))),
          /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()));
      DexProducedFromJavaLibrary preDex =
          new DexProducedFromJavaLibrary(paramsForPreDex, pathResolver, javaLibrary);
      ruleResolver.addToIndex(preDex);
      preDexDeps.add(preDex);
    }

    ImmutableSet<DexProducedFromJavaLibrary> allPreDexDeps = preDexDeps.build();

    BuildRuleParams paramsForPreDexMerge = buildRuleParams.copyWithChanges(
        BuildRuleType.DEX_MERGE,
        createBuildTargetWithFlavor(DEX_MERGE_FLAVOR),
        Suppliers.ofInstance(getDexMergeDeps(aaptPackageResources, allPreDexDeps)),
        /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()));
    PreDexMerge preDexMerge = new PreDexMerge(
        paramsForPreDexMerge,
        pathResolver,
        primaryDexPath,
        dexSplitMode,
        allPreDexDeps,
        aaptPackageResources);
    ruleResolver.addToIndex(preDexMerge);

    return preDexMerge;
  }

  private BuildTarget createBuildTargetWithFlavor(Flavor flavor) {
    return BuildTarget.builder(originalBuildTarget)
        .addFlavors(flavor)
        .build();
  }

  private ImmutableSortedSet<BuildRule> getAdditionalAaptDeps(
      SourcePathResolver resolver,
      ImmutableSortedSet<BuildRule> resourceRules,
      AndroidPackageableCollection packageableCollection) {
    ImmutableSortedSet.Builder<BuildRule> builder = ImmutableSortedSet.<BuildRule>naturalOrder()
        .addAll(resourceRules)
        .addAll(
            getTargetsAsRules(
                FluentIterable.from(
                    packageableCollection.getResourceDetails()
                        .getResourcesWithEmptyResButNonEmptyAssetsDir())
                    .transform(HasBuildTarget.TO_TARGET)
                    .toList()));
    Optional<BuildRule> manifestRule = resolver.getRule(manifest);
    if (manifestRule.isPresent()) {
      builder.add(manifestRule.get());
    }
    return builder.build();
  }

  private ImmutableSortedSet<BuildRule> getDexMergeDeps(
      AaptPackageResources aaptPackageResources,
      ImmutableSet<DexProducedFromJavaLibrary> preDexDeps) {
    ImmutableSet.Builder<BuildTarget> targets = ImmutableSet.builder();
    targets.add(aaptPackageResources.getBuildTarget());
    for (DexProducedFromJavaLibrary preDex : preDexDeps) {
      targets.add(preDex.getBuildTarget());
    }
    return getTargetsAsRules(targets.build());
  }

  private ImmutableSortedSet<BuildRule> getTargetsAsRules(Collection<BuildTarget> buildTargets) {
    return BuildRules.toBuildRulesFor(
        originalBuildTarget,
        ruleResolver,
        buildTargets,
        /* allowNonExistentRules */ false);
  }

  private ImmutableList<HasAndroidResourceDeps> getTargetsAsResourceDeps(
      Collection<BuildTarget> targets) {
    return FluentIterable.from(getTargetsAsRules(targets))
        .transform(new Function<BuildRule, HasAndroidResourceDeps>() {
                     @Override
                     public HasAndroidResourceDeps apply(BuildRule input) {
                       Preconditions.checkState(input instanceof HasAndroidResourceDeps);
                       return (HasAndroidResourceDeps) input;
                     }
                   })
        .toList();
  }
}
