// Copyright (c) 2019, 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.b128656974;

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.assertNotEquals;

import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NeverMerge;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.naming.testclasses.Greeting;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.FieldSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import org.junit.Test;

public class B128656974 extends TestBase {

  @Test
  public void testField() throws Exception {
    Class<?> main = TestClassMainForField.class;
    testForR8(Backend.DEX)
        .addProgramClasses(Greeting.class, Greeting.getGreetingBase(), TestClassSub.class, main)
        .enableNeverClassInliningAnnotations()
        .enableMergeAnnotations()
        .addKeepMainRule(main)
        .addKeepRules(
            "-keepclassmembernames class "
                + TestClassSub.class.getTypeName()
                + "{ static java.lang.String a; }")
        .run(main)
        .assertSuccessWithOutput(StringUtils.lines("TestClassSub.greeting", "TestClassSub.a"))
        .inspect(
            inspector -> {
              ClassSubject greetingBase = inspector.clazz(Greeting.getGreetingBase());
              assertThat(greetingBase, isPresent());
              FieldSubject greeting = greetingBase.uniqueFieldWithName("greeting");
              assertThat(greeting, isPresent());
              assertThat(greeting, isRenamed());
              assertNotEquals("a", greeting.getFinalName());
            });
  }

  @NeverClassInline
  static class TestClassSub extends Greeting {
    // Since this name is kept, renaming of Greeting.greeting should avoid `a`.
    // Otherwise, we'll see Out-of-order field_ids due to the duplicate fields.
    static String a;

    TestClassSub() {
      greeting = "TestClassSub.greeting";
      a = "TestClassSub.a";
    }

    @Override
    public String toString(){
      return greeting + System.lineSeparator() + a;
    }
  }

  static class TestClassMainForField {
    public static void main(String[] args) {
      TestClassSub instance = new TestClassSub();
      System.out.println(instance.toString());
    }
  }

  @Test
  public void testMethod() throws Exception {
    Class<?> main = TestClassMainForMethod.class;
    testForR8(Backend.DEX)
        .addProgramClasses(TestClassBase.class, TestClassSub2.class, main)
        .enableMergeAnnotations()
        .enableNeverClassInliningAnnotations()
        .enableInliningAnnotations()
        .addKeepMainRule(main)
        .addKeepRules(
            "-keepclassmembernames class " + TestClassSub2.class.getTypeName() + "{ void a(...); }")
        .run(main)
        .assertSuccessWithOutput(StringUtils.lines("TestClassSub2::a", "TestClassBase::foo"))
        .inspect(
            inspector -> {
              ClassSubject base = inspector.clazz(TestClassBase.class);
              assertThat(base, isPresent());
              MethodSubject foo = base.uniqueMethodWithName("foo");
              assertThat(foo, isPresent());
              assertThat(foo, isRenamed());
              assertNotEquals("a", foo.getFinalName());
            });
  }

  @NeverMerge
  static class TestClassBase {
    @NeverInline
    void foo() {
      System.out.println("TestClassBase::foo");
    }
  }

  @NeverClassInline
  static class TestClassSub2 extends TestClassBase {
    // Since this name is kept, renaming of TestClassBase#foo should avoid `a`.
    // Otherwise, we'll see Out-of-order method_ids due to the duplicate methods.
    @NeverInline
    void a() {
      System.out.println("TestClassSub2::a");
    }
  }

  static class TestClassMainForMethod {
    public static void main(String[] args) {
      TestClassSub2 instance = new TestClassSub2();
      instance.a();
      instance.foo();
    }
  }
}
