/*
 * 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.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.BuildRules;
import com.facebook.buck.rules.CellPathResolver;
import com.facebook.buck.rules.Description;
import com.facebook.buck.rules.TargetGraph;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.infer.annotation.SuppressFieldNotInitialized;
import com.google.common.collect.ImmutableSortedSet;
import java.util.Optional;

public class AndroidInstrumentationTestDescription
    implements Description<AndroidInstrumentationTestDescription.Arg> {

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

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

  @Override
  public Class<Arg> getConstructorArgType() {
    return Arg.class;
  }

  @Override
  public AndroidInstrumentationTest createBuildRule(
      TargetGraph targetGraph,
      BuildRuleParams params,
      BuildRuleResolver resolver,
      CellPathResolver cellRoots,
      Arg args) {
    BuildRule apk = resolver.getRule(args.apk);
    if (!(apk instanceof HasInstallableApk)) {
      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.copyAppendingExtraDeps(BuildRules.getExportedRules(params.getDeclaredDeps().get())),
        (HasInstallableApk) apk,
        args.labels,
        args.contacts,
        javaOptions.getJavaRuntimeLauncher(),
        args.testRuleTimeoutMs.map(Optional::of).orElse(defaultTestRuleTimeoutMs));
  }

  @SuppressFieldNotInitialized
  public static class Arg extends AbstractDescriptionArg {
    public BuildTarget apk;
    public ImmutableSortedSet<String> contacts = ImmutableSortedSet.of();
    public Optional<Long> testRuleTimeoutMs;
  }
}

@@ -731,63 +731,8 @@
 et;%0A
-import com.facebook.buck.rules.AbstractDescriptionArg;%0A
 impo
@@ -951,32 +951,85 @@
 llPathResolver;%0A
+import com.facebook.buck.rules.CommonDescriptionArg;%0A
 import com.faceb
@@ -1178,52 +1178,47 @@
 ook.
-infer.annotation.SuppressFieldNotInitialized
+buck.util.immutables.BuckStyleImmutable
 ;%0Aim
@@ -1294,16 +1294,51 @@
 ptional;
+%0Aimport org.immutables.value.Value;
 %0A%0Apublic
@@ -1446,17 +1446,16 @@
 cription
-.
 Arg%3E %7B%0A%0A
@@ -1805,16 +1805,53 @@
 c Class%3C
+AndroidInstrumentationTestDescription
 Arg%3E get
@@ -1884,16 +1884,53 @@
  return 
+AndroidInstrumentationTestDescription
 Arg.clas
@@ -2137,16 +2137,53 @@
 ,%0A      
+AndroidInstrumentationTestDescription
 Arg args
@@ -2228,19 +2228,24 @@
 le(args.
-apk
+getApk()
 );%0A    i
@@ -2761,14 +2761,19 @@
 rgs.
-l
+getL
 abels
+()
 ,%0A  
@@ -2783,24 +2783,29 @@
    args.
-c
+getC
 ontacts
+()
 ,%0A      
@@ -2857,17 +2857,20 @@
    args.
-t
+getT
 estRuleT
@@ -2877,16 +2877,18 @@
 imeoutMs
+()
 .map(Opt
@@ -2945,58 +2945,103 @@
 %0A  @
-SuppressFieldNotInitialized%0A  public static class 
+BuckStyleImmutable%0A  @Value.Immutable%0A  interface AbstractAndroidInstrumentationTestDescription
 Arg 
@@ -3048,24 +3048,22 @@
 extends 
-Abstract
+Common
 Descript
@@ -3075,23 +3075,16 @@
 g %7B%0A    
-public 
 BuildTar
@@ -3091,23 +3091,46 @@
 get 
-apk;%0A    public
+getApk();%0A%0A    @Value.NaturalOrder%0A   
  Imm
@@ -3157,55 +3157,28 @@
 ng%3E 
-c
+getC
 ontacts
- = ImmutableSortedSet.of
 ();%0A
+%0A
     
-public 
 Opti
@@ -3188,17 +3188,20 @@
 l%3CLong%3E 
-t
+getT
 estRuleT
@@ -3204,20 +3204,22 @@
 uleTimeoutMs
+()
 ;%0A  %7D%0A%7D%0A

Convert android_instrumentation_test Arg to be Immutable