// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8.shaking.attributes;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.R8TestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FieldSubject;
import com.android.tools.r8.utils.codeinspector.MemberSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@SuppressWarnings("ALL")
@RunWith(Parameterized.class)
public class KeepSignatureTest extends TestBase {

  private final TestParameters parameters;
  private final String[] EXPECTED = new String[] {"Hello", "World", "Hello", "World"};

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimesAndApiLevels().build();
  }

  public KeepSignatureTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  @Test
  public void testRuntime() throws Exception {
    testForRuntime(parameters)
        .addProgramClassFileData(transformer(KeptClass.class).removeInnerClasses().transform())
        .addProgramClassFileData(transformer(NotKeptClass.class).removeInnerClasses().transform())
        .run(parameters.getRuntime(), KeptClass.class)
        .assertSuccessWithOutputLines(EXPECTED);
  }

  @Test
  public void testKeptClassFieldAndMethodFull() throws Exception {
    // TODO(b/172999267): The below should be true
    runTest(testForR8(parameters.getBackend()), true);
  }

  @Test
  public void testKeptClassFieldAndMethodCompat() throws Exception {
    runTest(testForR8Compat(parameters.getBackend()), true);
  }

  private void runTest(R8TestBuilder<?> testBuilder, boolean keptForNotKept) throws Exception {
    testBuilder
        .addProgramClassFileData(transformer(KeptClass.class).removeInnerClasses().transform())
        .addProgramClassFileData(transformer(NotKeptClass.class).removeInnerClasses().transform())
        .addKeepMainRule(KeptClass.class)
        .addKeepRules(
            StringUtils.lines(
                "-keep class " + KeptClass.class.getTypeName() + " {",
                "  *** keptMethod(...);",
                "  *** keptField;",
                "}"))
        .addKeepAttributes(
            ProguardKeepAttributes.SIGNATURE,
            ProguardKeepAttributes.INNER_CLASSES,
            ProguardKeepAttributes.ENCLOSING_METHOD)
        .setMinApi(parameters.getApiLevel())
        .enableInliningAnnotations()
        .enableNeverClassInliningAnnotations()
        .run(parameters.getRuntime(), KeptClass.class)
        .assertSuccessWithOutputLines(EXPECTED)
        .inspect(inspector -> inspect(inspector, keptForNotKept));
  }

  private void inspect(CodeInspector inspector, boolean keepForNotKept) {
    ClassSubject keptClass = inspector.clazz(KeptClass.class);
    assertThat(keptClass, isPresent());
    assertEquals(
        "<T:Ljava/lang/Object;>Ljava/lang/Object;", keptClass.getFinalSignatureAttribute());
    FieldSubject keptField = keptClass.uniqueFieldWithName("keptField");
    assertThat(keptField, isPresent());
    assertEquals("TT;", keptField.getFinalSignatureAttribute());
    MethodSubject keptMethod = keptClass.uniqueMethodWithName("keptMethod");
    assertThat(keptMethod, isPresent());
    assertEquals("<R:Ljava/lang/Object;>(TT;)TR;", keptMethod.getFinalSignatureAttribute());

    // For all remaining classes and members, we should only keep signatures if in compat mode.
    checkMemberSignature(keptClass.uniqueFieldWithName("notKeptField"), keepForNotKept, "TT;");
    checkMemberSignature(
        keptClass.uniqueMethodWithName("notKeptMethod"),
        keepForNotKept,
        "<R:Ljava/lang/Object;>(TT;)TR;");

    ClassSubject notKeptClass = inspector.clazz(NotKeptClass.class);
    assertThat(notKeptClass, isPresent());
    if (keepForNotKept) {
      assertEquals(
          "<P:Ljava/lang/Object;>Ljava/lang/Object;", notKeptClass.getFinalSignatureAttribute());
    } else {
      assertNull(notKeptClass.getFinalSignatureAttribute());
    }
    checkMemberSignature(
        notKeptClass.uniqueFieldWithName("notKeptField"), keepForNotKept, "Ljava/util/List<TP;>;");
    checkMemberSignature(
        notKeptClass.uniqueMethodWithName("notKeptMethod"),
        keepForNotKept,
        "(TP;TP;)Ljava/util/List<TP;>;");
  }

  private void checkMemberSignature(
      MemberSubject member, boolean keepForNotKept, String signature) {
    assertThat(member, isPresent());
    if (keepForNotKept) {
      assertEquals(signature, member.getFinalSignatureAttribute());
    } else {
      assertNull(member.getFinalSignatureAttribute());
    }
  }

  @NeverClassInline
  public static class NotKeptClass<P> {

    public List<P> notKeptField;

    @NeverInline
    public List<P> notKeptMethod(P p1, P p2) {
      if (notKeptField != null) {
        return notKeptField;
      }
      ArrayList<P> ps = new ArrayList<>();
      ps.add(p1);
      ps.add(p2);
      notKeptField = ps;
      return ps;
    }
  }

  public static class KeptClass<T> {

    private T keptField;
    private T notKeptField;

    @SuppressWarnings("unchecked")
    public <R> R keptMethod(T t) {
      if (keptField == null) {
        keptField = t;
      }
      return (R) keptField;
    }

    @NeverInline
    @SuppressWarnings("unchecked")
    public <R> R notKeptMethod(T t) {
      if (notKeptField == null) {
        notKeptField = t;
      }
      return (R) notKeptField;
    }

    public static void main(String[] args) {
      KeptClass<String> keptClass = new KeptClass<>();
      System.out.println(keptClass.<String>keptMethod("Hello"));
      System.out.println(keptClass.<String>notKeptMethod("World"));
      NotKeptClass<String> stringNotKeptClass = new NotKeptClass<>();
      List<String> strings = stringNotKeptClass.notKeptMethod("Hello", "World");
      System.out.println(strings.get(0));
      System.out.println(strings.get(1));
    }
  }
}
