// 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.shaking.assumenosideeffects;

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

import com.android.tools.r8.NeverInline;
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.StringUtils;
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 org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class AssumenosideeffectsPropagationWithoutMatchingDefinitionTest extends TestBase {
  private static final Class<?> MAIN = B137038659.class;
  private static final String OUTPUT_WITHOUT_LOGGING = StringUtils.lines(
      "The end"
  );

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

  private final TestParameters parameters;

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

  @Test
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .addInnerClasses(AssumenosideeffectsPropagationWithoutMatchingDefinitionTest.class)
        .enableMergeAnnotations()
        .enableInliningAnnotations()
        .addKeepMainRule(MAIN)
        .addKeepRules(
            "-assumenosideeffects class * implements " + LoggerInterface.class.getTypeName() + " {",
            "  *** debug(...);",
            "}")
        .noMinification()
        .setMinApi(parameters.getRuntime())
        .run(parameters.getRuntime(), MAIN)
        .assertSuccessWithOutput(OUTPUT_WITHOUT_LOGGING)
        .inspect(this::inspect);
  }

  private void inspect(CodeInspector inspector) {
    ClassSubject main = inspector.clazz(MAIN);
    assertThat(main, isPresent());

    MethodSubject mainMethod = main.mainMethod();
    assertThat(mainMethod, isPresent());
    assertTrue(
        mainMethod.streamInstructions().noneMatch(
            i -> i.isInvoke() && i.getMethod().name.toString().equals("debug")));

    MethodSubject testInvokeInterface = main.uniqueMethodWithName("testInvokeInterface");
    assertThat(testInvokeInterface, not(isPresent()));
  }

  interface LoggerInterface {
    void debug(String message);
    void debug(String tag, String message);
  }

  @NeverMerge
  static class BaseImplementer implements LoggerInterface {
    @Override
    public void debug(String message) {
      System.out.println("[Base]: " + message);
    }

    @Override
    public void debug(String tag, String message) {
      System.out.println(tag + ": " + message);
    }
  }

  static class SubImplementer extends BaseImplementer implements LoggerInterface {
    // Intentionally empty
    // b/137038659: Since there is no method definition in this class, no rules are bound. We
    // propagated assume* rules only if all the subtypes' corresponding methods have the same rule.
    // The lack of matching definitions in this sub type blocks us from marking methods in the super
    // type, in this example, LoggerInterface#debug(...).
    // By using a resolved target, we will look up a rule for BaseImplementer#debug(...) instead.
  }

  // To bother single target resolution. In fact, not used at all.
  static class AnotherLogger implements LoggerInterface {
    @Override
    public void debug(String message) {
      System.out.println("[AnotherLogger]: " + message);
    }

    @Override
    public void debug(String tag, String message) {
      System.out.println("[" + tag + "] " + message);
    }
  }

  static class B137038659 {
    final static String TAG = B137038659.class.getSimpleName();

    @NeverInline
    private static void testInvokeInterface(LoggerInterface logger, String message) {
      if (logger != null) {
        logger.debug(TAG, message);
      }
    }

    @NeverInline
    private static LoggerInterface getLogger() {
      return System.currentTimeMillis() > 0 ? new SubImplementer()
          : (System.nanoTime() > 0 ? new BaseImplementer() : new AnotherLogger());
    }

    public static void main(String... args) {
      LoggerInterface logger = getLogger();
      testInvokeInterface(logger, "message1");
      logger.debug("message2");
      System.out.println("The end");
    }
  }
}
