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

import com.android.tools.r8.DesugarTestConfiguration;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ir.desugar.itf.InterfaceMethodRewriter;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.concurrent.Callable;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

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

  private List<String> EXPECTED_RESULT_WITHOUT_DESUGARING =
      ImmutableList.of(
          WithAnonymousInner.class.getName(), "true", WithLocalInner.class.getName(), "true");

  private List<String> EXPECTED_RESULT_WITH_DESUGARING =
      ImmutableList.of(
          WithAnonymousInner.class.getName() + InterfaceMethodRewriter.COMPANION_CLASS_NAME_SUFFIX,
          "true",
          WithLocalInner.class.getName() + InterfaceMethodRewriter.COMPANION_CLASS_NAME_SUFFIX,
          "true");

  private List<String> EXPECTED_RESULT_WITH_DESUGARING_B168697955 =
      ImmutableList.of(
          WithAnonymousInner.class.getName() + InterfaceMethodRewriter.COMPANION_CLASS_NAME_SUFFIX,
          "false",
          WithLocalInner.class.getName() + InterfaceMethodRewriter.COMPANION_CLASS_NAME_SUFFIX,
          "false");

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

  private final TestParameters parameters;

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

  @Test
  public void testDesugar() throws Exception {
    testForDesugaring(parameters)
        .addInnerClasses(DesugarInnerClassesInInterfaces.class)
        .run(parameters.getRuntime(), TestClass.class)
        .applyIf(
            DesugarTestConfiguration::isNotDesugared,
            r -> r.assertSuccessWithOutputLines(EXPECTED_RESULT_WITHOUT_DESUGARING))
        .applyIf(
            DesugarTestConfiguration::isDesugared,
            r ->
                r.assertSuccessWithOutputLines(
                    parameters
                            .getApiLevel()
                            .isGreaterThanOrEqualTo(apiLevelWithDefaultInterfaceMethodsSupport())
                        ? EXPECTED_RESULT_WITHOUT_DESUGARING
                        : EXPECTED_RESULT_WITH_DESUGARING));
  }

  @Test
  public void testR8() throws Exception {
    R8TestRunResult result =
        testForR8(parameters.getBackend())
            .addInnerClasses(DesugarInnerClassesInInterfaces.class)
            .setMinApi(parameters.getApiLevel())
            .addKeepRules("-keep class * { *; }")
            .addKeepAttributes("InnerClasses", "EnclosingMethod")
            .compile()
            .run(parameters.getRuntime(), TestClass.class);
    if (parameters.canUseDefaultAndStaticInterfaceMethods()) {
      result.assertSuccessWithOutputLines(EXPECTED_RESULT_WITHOUT_DESUGARING);
    } else {
      // The static method which is moved to the companion class is inlined and causing
      // this different output. The rule "-keep class * { *; }" does not keep the static
      // method from being inlined after it has moved. Turning off inlining produces the
      // expected result. The inlining cause the getEnclosingClass() to return null.
      // See b/168697955.
      result.assertSuccessWithOutputLines(EXPECTED_RESULT_WITH_DESUGARING_B168697955);
    }
  }

  @Test
  public void testR8_B168697955() throws Exception {
    R8TestRunResult result =
        testForR8(parameters.getBackend())
            .addInnerClasses(DesugarInnerClassesInInterfaces.class)
            .setMinApi(parameters.getApiLevel())
            .addKeepRules("-keep class * { *; }")
            .addKeepAttributes("InnerClasses", "EnclosingMethod")
            // With inlining turned off we get the expected result.
            .addOptionsModification(options -> options.enableInlining = false)
            .compile()
            .run(parameters.getRuntime(), TestClass.class);
    if (parameters.canUseDefaultAndStaticInterfaceMethods()) {
      result.assertSuccessWithOutputLines(EXPECTED_RESULT_WITHOUT_DESUGARING);
    } else {
      result.assertSuccessWithOutputLines(EXPECTED_RESULT_WITH_DESUGARING);
    }
  }

  interface WithAnonymousInner {
    static Callable<Class<?>> staticOuter() {
      return new Callable<Class<?>>() {
        @Override
        public Class<?> call() throws Exception {
          return getClass().getEnclosingClass();
        }
      };
    }

    default Callable<Class<?>> defaultOuter() {
      return new Callable<Class<?>>() {
        @Override
        public Class<?> call() throws Exception {
          return getClass().getEnclosingClass();
        }
      };
    }
  }

  interface WithLocalInner {
    static Callable<Class<?>> staticOuter() {
      class Local implements Callable<Class<?>> {
        @Override
        public Class<?> call() throws Exception {
          return getClass().getEnclosingClass();
        }
      }
      return new Local();
    }

    default Callable<Class<?>> defaultOuter() {
      class Local implements Callable<Class<?>> {
        @Override
        public Class<?> call() throws Exception {
          return getClass().getEnclosingClass();
        }
      }
      return new Local();
    }
  }

  public static class TestClass {

    public static void main(String[] args) throws Exception {
      System.out.println(new WithAnonymousInner() {}.defaultOuter().call().getName());
      System.out.println(
          new WithAnonymousInner() {}.defaultOuter()
              .call()
              .equals(WithAnonymousInner.staticOuter().call()));
      System.out.println(new WithLocalInner() {}.defaultOuter().call().getName());
      System.out.println(
          new WithLocalInner() {}.defaultOuter()
              .call()
              .equals(WithLocalInner.staticOuter().call()));
    }
  }
}
