/*
 * Copyright 2015-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.jvm.java.JavaOptions;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.HasSourceUnderTest;
import com.facebook.buck.rules.AbstractDescriptionArg;
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.Description;
import com.facebook.buck.rules.InstallableApk;
import com.facebook.buck.rules.Label;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.TargetGraph;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.infer.annotation.SuppressFieldNotInitialized;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;

public class AndroidInstrumentationTestDescription
    implements Description<AndroidInstrumentationTestDescription.Arg> {

  public static final BuildRuleType TYPE = BuildRuleType.of("android_instrumentation_test");

  private final JavaOptions javaOptions;
  private final Optional<Long> defaultTestRuleTimeoutMs;

  public AndroidInstrumentationTestDescription(
      JavaOptions javaOptions,
      Optional<Long> defaultTestRuleTimeoutMs) {
    this.javaOptions = javaOptions;
    this.defaultTestRuleTimeoutMs = defaultTestRuleTimeoutMs;
  }

  @Override
  public BuildRuleType getBuildRuleType() {
    return TYPE;
  }

  @Override
  public Arg createUnpopulatedConstructorArg() {
    return new Arg();
  }

  @Override
  public <A extends Arg> AndroidInstrumentationTest createBuildRule(
      TargetGraph targetGraph,
      BuildRuleParams params,
      BuildRuleResolver resolver,
      A args) {
    BuildRule apk = resolver.getRule(args.apk);
    if (!(apk instanceof InstallableApk)) {
      throw new HumanReadableException(
          "In %s, instrumentation_apk='%s' must be an android_binary(), apk_genrule() or " +
          "android_instrumentation_apk(), but was %s().",
          params.getBuildTarget(),
          apk.getFullyQualifiedName(),
          apk.getType());
    }

    return new AndroidInstrumentationTest(
        params.appendExtraDeps(
                BuildRules.getExportedRules(
                        params.getDeclaredDeps().get())),
        new SourcePathResolver(resolver),
        (InstallableApk) apk,
        args.labels.get(),
        args.contacts.get(),
        javaOptions.getJavaRuntimeLauncher(),
        args.testRuleTimeoutMs.or(defaultTestRuleTimeoutMs));
  }

  public static ImmutableSet<BuildRule> validateAndGetSourcesUnderTest(
      ImmutableSet<BuildTarget> sourceUnderTestTargets,
      BuildRuleResolver resolver) {
    ImmutableSet.Builder<BuildRule> sourceUnderTest = ImmutableSet.builder();
    for (BuildTarget target : sourceUnderTestTargets) {
      BuildRule rule = resolver.getRule(target);
      sourceUnderTest.add(rule);
    }
    return sourceUnderTest.build();
  }


  @SuppressFieldNotInitialized
  public static class Arg extends AbstractDescriptionArg implements HasSourceUnderTest {
    public BuildTarget apk;
    public Optional<ImmutableSortedSet<Label>> labels;
    public Optional<ImmutableSortedSet<String>> contacts;
    public Optional<ImmutableSortedSet<BuildTarget>> sourceUnderTest;
    public Optional<Long> testRuleTimeoutMs;

    @Override
    public ImmutableSortedSet<BuildTarget> getSourceUnderTest() {
      return sourceUnderTest.get();
    }
  }

}

@@ -731,59 +731,8 @@
 et;%0A
-import com.facebook.buck.model.HasSourceUnderTest;%0A
 impo
@@ -1399,55 +1399,8 @@
 al;%0A
-import com.google.common.collect.ImmutableSet;%0A
 impo
@@ -3168,436 +3168,8 @@
  %7D%0A%0A
-  public static ImmutableSet%3CBuildRule%3E validateAndGetSourcesUnderTest(%0A      ImmutableSet%3CBuildTarget%3E sourceUnderTestTargets,%0A      BuildRuleResolver resolver) %7B%0A    ImmutableSet.Builder%3CBuildRule%3E sourceUnderTest = ImmutableSet.builder();%0A    for (BuildTarget target : sourceUnderTestTargets) %7B%0A      BuildRule rule = resolver.getRule(target);%0A      sourceUnderTest.add(rule);%0A    %7D%0A    return sourceUnderTest.build();%0A  %7D%0A%0A%0A
   @S
@@ -3256,38 +3256,8 @@
 Arg 
-implements HasSourceUnderTest 
 %7B%0A  
@@ -3419,225 +3419,32 @@
 nal%3C
-ImmutableSortedSet%3CBuildTarget%3E%3E sourceUnderTest;%0A    public Optional%3CLong%3E testRuleTimeoutMs;%0A%0A    @Override%0A    public ImmutableSortedSet%3CBuildTarget%3E getSourceUnderTest() %7B%0A      return sourceUnderTest.get();%0A    %7D
+Long%3E testRuleTimeoutMs;
 %0A  %7D

Remove HasSourceUnderTest.