// 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.isCfRuntime()) {
      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()
            .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());
  }
}
