// Copyright (c) 2018, 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.naming.applymapping.sourcelibrary;

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

import com.android.tools.r8.NeverMerge;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.FileUtils;
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.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

// AbstractChecker -> X:
@NeverMerge
abstract class AbstractChecker {
  // String tag -> p
  private String tag = "PrivateInitialTag_AbstractChecker";

  // check() -> x
  private void check() {
    System.out.println("AbstractChecker#check:" + tag);
  }

  // foo() -> a
  protected void foo() {
    check();
  }
}

// ConcreteChecker -> Y:
class ConcreteChecker extends AbstractChecker {
  // This should not be conflict with AbstractChecker#tag due to the access control.
  // String tag -> q
  private String tag = "PrivateInitialTag_ConcreteChecker";

  ConcreteChecker(String tag) {
    this.tag = tag;
  }

  // This should not be conflict with AbstractChecker#check due to the access control.
  // check() -> y
  private void check() {
    System.out.println("ConcreteChecker#check:" + tag);
  }

  // foo() -> a
  @Override
  protected void foo() {
    super.foo();
    check();
  }
}

class MemberResolutionTestMain {
  public static void main(String[] args) {
    ConcreteChecker c = new ConcreteChecker("NewTag");
    c.foo();
  }
}

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

  private final TestParameters parameters;

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

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

  @Test
  public void testPrivateMethodsWithSameName() throws Exception {
    String pkg = this.getClass().getPackage().getName();
    Path mapPath = temp.newFile("test-mapping.txt").toPath();
    List<String> pgMap =
        ImmutableList.of(
            pkg + ".AbstractChecker -> " + pkg + ".X:",
            "  java.lang.String tag -> p",
            "  void check() -> x",
            "  void foo() -> a",
            pkg + ".ConcreteChecker -> " + pkg + ".Y:",
            "  java.lang.String tag -> q",
            "  void check() -> y",
            "  void foo() -> a");
    FileUtils.writeTextFile(mapPath, pgMap);

    String expectedOutput =
        StringUtils.lines(
            "AbstractChecker#check:PrivateInitialTag_AbstractChecker",
            "ConcreteChecker#check:NewTag");

    if (parameters.getBackend() == Backend.CF) {
      testForJvm()
          .addTestClasspath()
          .run(parameters.getRuntime(), MemberResolutionTestMain.class)
          .assertSuccessWithOutput(expectedOutput);
    }

    CodeInspector inspector =
        testForR8(parameters.getBackend())
            .addProgramClasses(
                AbstractChecker.class, ConcreteChecker.class, MemberResolutionTestMain.class)
            .addKeepMainRule(MemberResolutionTestMain.class)
            .addKeepRules("-applymapping " + mapPath)
            .enableMergeAnnotations()
            .noMinification()
            .addOptionsModification(options -> options.enableInlining = false)
            .setMinApi(parameters.getRuntime())
            .run(parameters.getRuntime(), MemberResolutionTestMain.class)
            .assertSuccessWithOutput(expectedOutput)
            .inspector();

    ClassSubject base = inspector.clazz(AbstractChecker.class);
    assertThat(base, isPresent());
    FieldSubject p = base.field("java.lang.String", "tag");
    assertThat(p, isPresent());
    assertThat(p, isRenamed());
    assertEquals("p", p.getFinalName());
    MethodSubject x = base.method("void", "check", ImmutableList.of());
    assertThat(x, isPresent());
    assertThat(x, isRenamed());
    assertEquals("x", x.getFinalName());

    ClassSubject sub = inspector.clazz(ConcreteChecker.class);
    assertThat(sub, isPresent());
    FieldSubject q = sub.field("java.lang.String", "tag");
    assertThat(q, isPresent());
    assertThat(q, isRenamed());
    assertEquals("q", q.getFinalName());
    MethodSubject y = sub.method("void", "check", ImmutableList.of());
    assertThat(y, isPresent());
    assertThat(y, isRenamed());
    assertEquals("y", y.getFinalName());
  }
}
