// 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.maindexlist;

import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.D8TestCompileResult;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.nio.file.Files;
import java.nio.file.Path;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

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

  static final AndroidApiLevel nativeMultiDexLevel = AndroidApiLevel.L;

  static final String EXPECTED = StringUtils.lines("AB");

  private final TestParameters parameters;

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

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

  @Test
  public void testFinal() throws Exception {
    if (parameters.isCfRuntime()) {
      testForJvm()
          .addTestClasspath()
          .run(parameters.getRuntime(), TestClass.class)
          .assertSuccessWithOutput(EXPECTED);
    } else {
      D8TestCompileResult compileResult =
          testForD8()
              .addInnerClasses(MainDexWithSynthesizedClassesTest.class)
              .addMainDexListClasses(TestClass.class, A.class)
              .setMinApiThreshold(parameters.getApiLevel())
              .compile();
      checkCompilationResult(compileResult);
    }
  }

  @Test
  public void testIntermediate() throws Exception {
    assumeTrue(parameters.isDexRuntime());
    D8TestCompileResult intermediateResult =
        testForD8()
            .addInnerClasses(MainDexWithSynthesizedClassesTest.class)
            .setMinApiThreshold(parameters.getApiLevel())
            .setIntermediate(true)
            .compile();
    D8TestCompileResult compileResult =
        testForD8()
            .addProgramFiles(intermediateResult.writeToZip())
            .addMainDexListClasses(TestClass.class, A.class)
            .setMinApiThreshold(parameters.getApiLevel())
            .compile();
    checkCompilationResult(compileResult);
  }

  private void checkCompilationResult(D8TestCompileResult compileResult) throws Exception {
    if (parameters.getRuntime().asDex().getMinApiLevel().getLevel()
        < nativeMultiDexLevel.getLevel()) {
      compileResult.runDex2Oat(parameters.getRuntime()).assertNoVerificationErrors();
    } else {
      compileResult.run(parameters.getRuntime(), TestClass.class).assertSuccessWithOutput(EXPECTED);
    }
    Path out = temp.newFolder().toPath();
    compileResult.apply(b -> b.app.writeToDirectory(out, OutputMode.DexIndexed));
    Path classes = out.resolve("classes.dex");
    Path classes2 = out.resolve("classes2.dex");
    assertTrue(Files.exists(classes));
    assertTrue(Files.exists(classes2));
    checkContainsLambdaClasses(new CodeInspector(classes), A.class);
    checkContainsLambdaClasses(new CodeInspector(classes2), B.class);
  }

  private void checkContainsLambdaClasses(CodeInspector inspector, Class<?> lambdaHolder) {
    assertTrue(
        inspector.allClasses().stream()
            .anyMatch(
                clazz ->
                    clazz.isSynthesizedJavaLambdaClass()
                        && clazz
                            .getOriginalReference()
                            .equals(
                                SyntheticItemsTestUtils.syntheticLambdaClass(lambdaHolder, 0))));
  }

  static class TestClass {
    public static void main(String[] args) {
      System.out.println(new A().foo().get());
    }
  }

  interface Getter {
    String get();
  }

  static class A {
    Getter foo() {
      return () -> "A" + new B().foo().get();
    }
  }

  static class B {
    Getter foo() {
      return () -> "B";
    }
  }
}
