/*
 * Copyright 2017-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.io.ProjectFilesystem;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.Flavor;
import com.facebook.buck.model.InternalFlavor;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.NoopBuildRule;
import com.facebook.buck.rules.SourcePathRuleFinder;
import com.google.common.collect.ImmutableSortedSet;
import java.util.Optional;
import java.util.SortedSet;

class AndroidBinaryInstallGraphEnhancer {
  static final Flavor INSTALL_FLAVOR = InternalFlavor.of("install");

  private ProjectFilesystem projectFilesystem;
  private BuildTarget buildTarget;
  private AndroidBinary androidBinary;
  private AndroidInstallConfig androidInstallConfig;

  AndroidBinaryInstallGraphEnhancer(
      AndroidInstallConfig androidInstallConfig,
      ProjectFilesystem projectFilesystem,
      BuildTarget buildTarget,
      AndroidBinary androidBinary) {
    this.projectFilesystem = projectFilesystem;
    this.buildTarget = buildTarget.withFlavors(INSTALL_FLAVOR);
    this.androidBinary = androidBinary;
    this.androidInstallConfig = androidInstallConfig;
  }

  private BuildRule createExoInstaller(
      BuildTarget buildTarget,
      ProjectFilesystem filesystem,
      BuildRuleResolver resolver,
      AndroidBinary binary,
      AndroidInstallConfig androidInstallConfig) {
    BuildRule installer;
    if (androidInstallConfig.getConcurrentInstallEnabled(
        Optional.ofNullable(resolver.getEventBus()))) {
      installer =
          new ExoInstaller(buildTarget, filesystem, new SourcePathRuleFinder(resolver), binary);
    } else {
      installer =
          new NoopBuildRule(buildTarget, filesystem) {
            @Override
            public SortedSet<BuildRule> getBuildDeps() {
              return ImmutableSortedSet.of();
            }
          };
    }
    resolver.addToIndex(installer);
    return installer;
  }

  public void enhance(BuildRuleResolver resolver) {
    resolver.addToIndex(
        createExoInstaller(
            buildTarget, projectFilesystem, resolver, androidBinary, androidInstallConfig));
  }
}

@@ -1815,722 +1815,594 @@
 %0A  p
-rivate BuildRule createExoInstaller(%0A      BuildTarget buildTarget,%0A      ProjectFilesystem filesystem,%0A      BuildRuleResolver resolver,%0A      AndroidBinary binary,%0A      AndroidInstallConfig androidInstallConfig) %7B%0A    BuildRule installer;%0A    if (androidInstallConfig.getConcurrentInstallEnabled(%0A        Optional.ofNullable(resolver.getEventBus()))) %7B%0A      installer =%0A          new ExoInstaller(buildTarget, filesystem, new SourcePathRuleFinder(resolver), binary);%0A    %7D else %7B%0A      installer =
+ublic void enhance(BuildRuleResolver resolver) %7B%0A    if (androidInstallConfig.getConcurrentInstallEnabled(%0A        Optional.ofNullable(resolver.getEventBus()))) %7B%0A      if (exopackageEnabled()) %7B%0A        enhanceForConcurrentExopackageInstall(resolver);%0A      %7D else %7B%0A        enhanceForConcurrentInstall(resolver);
 %0A      
+%7D%0A
     
-new NoopBuildRule(buildTarget, filesystem) %7B%0A            @Override%0A            public SortedSet%3CBuildRule%3E getBuildDeps() %7B%0A              return ImmutableSortedSet.of();%0A            %7D%0A          %7D;%0A    %7D
+%7D else %7B%0A      enhanceForLegacyInstall(resolver);%0A    %7D%0A  %7D%0A%0A  private boolean exopackageEnabled() %7B%0A    return androidBinary.getApkInfo().getExopackageInfo().isPresent();%0A  %7D%0A%0A  private void enhanceForConcurrentExopackageInstall(BuildRuleResolver resolver) %7B
 %0A   
@@ -2422,25 +2422,41 @@
 ToIndex(
-i
+%0A        new ExoI
 nstaller
 );%0A    r
@@ -2451,31 +2451,105 @@
 ller
-);
+(
 %0A    
-return installer
+        buildTarget, projectFilesystem, new SourcePathRuleFinder(resolver), androidBinary))
 ;%0A  
@@ -2546,37 +2546,38 @@
 nary));%0A  %7D%0A%0A  p
-ublic
+rivate
  void enhance(Bu
@@ -2565,32 +2565,52 @@
 ate void enhance
+ForConcurrentInstall
 (BuildRuleResolv
@@ -2661,14 +2661,12 @@
     
-create
+new 
 ExoI
@@ -2719,24 +2719,49 @@
 system, 
+new SourcePathRuleFinder(
 resolver
 , androi
@@ -2752,16 +2752,17 @@
 resolver
+)
 , androi
@@ -2772,31 +2772,311 @@
 nary
-, androidInstallConfig)
+));%0A  %7D%0A%0A  private void enhanceForLegacyInstall(BuildRuleResolver resolver) %7B%0A    resolver.addToIndex(%0A        new NoopBuildRule(buildTarget, projectFilesystem) %7B%0A          @Override%0A          public SortedSet%3CBuildRule%3E getBuildDeps() %7B%0A            return ImmutableSortedSet.of();%0A          %7D%0A        %7D
 );%0A 

Split AndroidBinaryInstallGraphEnhancer.enhance()