// Copyright (c) 2021, 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.graph.genericsignature;

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

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.graph.genericsignature.GenericSignatureKeepAttributesTest.Outer.Middle;
import com.android.tools.r8.graph.genericsignature.GenericSignatureKeepAttributesTest.Outer.Middle.Inner;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class GenericSignatureKeepAttributesTest extends TestBase {

  private final TestParameters parameters;
  private final boolean isCompat;

  private final String[] EXPECTED_JVM =
      new String[] {
        "Outer.Middle.Inner::test",
        "public class com.android.tools.r8.graph.genericsignature"
            + ".GenericSignatureKeepAttributesTest$Outer$Middle$Inner<I>"
      };

  private final String[] EXPECTED_DEX =
      new String[] {
        "Outer.Middle.Inner::test",
        "class com.android.tools.r8.graph.genericsignature"
            + ".GenericSignatureKeepAttributesTest$Outer$Middle$Inner"
      };

  @Parameters(name = "{0}, isCompat: {1}")
  public static List<Object[]> data() {
    return buildParameters(
        getTestParameters().withAllRuntimesAndApiLevels().build(), BooleanUtils.values());
  }

  public GenericSignatureKeepAttributesTest(TestParameters parameters, boolean isCompat) {
    this.parameters = parameters;
    this.isCompat = isCompat;
  }

  @Test
  public void testRuntime() throws Exception {
    testForRuntime(parameters)
        .addProgramClasses(Supplier.class, Predicate.class, Outer.class, Middle.class, Main.class)
        .addProgramClassFileData(getClassFileData())
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutputLines(parameters.isCfRuntime() ? EXPECTED_JVM : EXPECTED_DEX);
  }

  @Test
  public void testR8() throws Exception {
    (isCompat ? testForR8Compat(parameters.getBackend()) : testForR8(parameters.getBackend()))
        .addProgramClasses(Supplier.class, Predicate.class, Outer.class, Middle.class, Main.class)
        .addProgramClassFileData(getClassFileData())
        .setMinApi(parameters.getApiLevel())
        .addKeepAttributeSignature()
        .addKeepAttributeInnerClassesAndEnclosingMethod()
        .addKeepMainRule(Main.class)
        .addKeepClassAndMembersRules(Outer.Middle.Inner.class, Supplier.class, Predicate.class)
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutputLines(parameters.isCfRuntime() ? EXPECTED_JVM : EXPECTED_DEX)
        .inspect(this::inspectSignatures);
  }

  private byte[] getClassFileData() throws Exception {
    return transformer(Inner.class)
        .transformMethodInsnInMethod(
            "test",
            ((opcode, owner, name, descriptor, isInterface, continuation) -> {
              if (parameters.isCfRuntime() && name.equals("toString")) {
                name = "toGenericString";
              }
              continuation.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
            }))
        .transform();
  }

  private void inspectSignatures(CodeInspector inspector) {
    ClassSubject outerClass = inspector.clazz(Outer.class);
    assertThat(outerClass, isPresent());
    assertEquals(
        isCompat ? "<O::L" + binaryName(Supplier.class) + "<*>;>Ljava/lang/Object;" : null,
        outerClass.getFinalSignatureAttribute());

    ClassSubject middleClass = inspector.clazz(Middle.class);
    assertThat(middleClass, isPresent());
    assertEquals(
        isCompat ? "<M::L" + binaryName(Predicate.class) + "<TO;>;>Ljava/lang/Object;" : null,
        middleClass.getFinalSignatureAttribute());

    ClassSubject innerClass = inspector.clazz(Inner.class);
    assertThat(innerClass, isPresent());
    MethodSubject testMethod = innerClass.uniqueMethodWithName("test");
    assertThat(testMethod, isPresent());
    if (isCompat) {
      assertEquals("(TO;TM;)TI;", testMethod.getFinalSignatureAttribute());
    } else {
      assertEquals(
          "(" + descriptor(Supplier.class) + descriptor(Predicate.class) + ")TI;",
          testMethod.getFinalSignatureAttribute());
    }
  }

  public interface Supplier<T> {}

  public interface Predicate<T> {}

  public static class Outer<O extends Supplier<?>> {

    public class Middle<M extends Predicate<O>> {

      public class Inner<I> {

        public I test(O o, M m) {
          System.out.println("Outer.Middle.Inner::test");
          System.out.println(this.getClass().toString()); // .toGenericString() for JVMs
          return null;
        }
      }

      private Outer<O>.Middle<M>.Inner<Object> createInner() {
        return new Inner<>();
      }
    }

    private Outer<O>.Middle<?> createMiddle() {
      return new Outer<O>.Middle<>();
    }

    public static Outer<?>.Middle<?>.Inner<Object> create() {
      return new Outer<>().createMiddle().createInner();
    }
  }

  public static class Main {

    public static void main(String[] args) {
      Outer.create().test(null, null);
    }
  }
}
