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

import static com.android.tools.r8.ToolHelper.isLocalDevelopment;
import static com.android.tools.r8.ToolHelper.shouldRunSlowTests;
import static com.android.tools.r8.internal.proto.ProtoShrinkingTestBase.assertRewrittenProtoSchemasMatch;
import static com.android.tools.r8.internal.proto.ProtoShrinkingTestBase.keepAllProtosRule;
import static com.android.tools.r8.internal.proto.ProtoShrinkingTestBase.keepDynamicMethodSignatureRule;
import static com.android.tools.r8.internal.proto.ProtoShrinkingTestBase.keepNewMessageInfoSignatureRule;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.L8TestCompileResult;
import com.android.tools.r8.LibraryDesugaringTestConfiguration.PresentKeepRuleConsumer;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.StringResource;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ThrowableConsumer;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ExecutionException;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class YouTubeV1612Test extends YouTubeCompilationTestBase {

  private static final int MAX_APPLICATION_SIZE = 29000000;
  private static final int MAX_DESUGARED_LIBRARY_SIZE = 375000;

  private final TestParameters parameters;

  private final Path dumpDirectory = Paths.get("YouTubeV1612-" + System.currentTimeMillis());
  private final Reporter reporter = new Reporter();

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters()
        .withDexRuntime(Version.V9_0_0)
        .withApiLevel(AndroidApiLevel.L)
        .build();
  }

  public YouTubeV1612Test(TestParameters parameters) {
    super(16, 12, parameters.getApiLevel());
    this.parameters = parameters;
  }

  @Test
  public void test() throws Exception {
    assumeTrue(isLocalDevelopment());
    assumeTrue(shouldRunSlowTests());

    KeepRuleConsumer keepRuleConsumer = new PresentKeepRuleConsumer();
    R8TestCompileResult r8CompileResult = compileApplicationWithR8(keepRuleConsumer);
    L8TestCompileResult l8CompileResult = compileDesugaredLibraryWithL8(keepRuleConsumer);

    inspect(r8CompileResult, l8CompileResult);

    if (isLocalDevelopment()) {
      dump(r8CompileResult, l8CompileResult);
    }
  }

  @Test
  public void testProtoRewriting() throws Exception {
    assumeTrue(shouldRunSlowTests());

    StringConsumer keepRuleConsumer = StringConsumer.emptyConsumer();
    R8TestCompileResult r8CompileResult =
        compileApplicationWithR8(
            keepRuleConsumer,
            builder ->
                builder
                    .addKeepRules(
                        keepAllProtosRule(),
                        keepDynamicMethodSignatureRule(),
                        keepNewMessageInfoSignatureRule())
                    .allowCheckDiscardedErrors(true));
    assertRewrittenProtoSchemasMatch(
        new CodeInspector(getProgramFiles()), r8CompileResult.inspector());
  }

  @After
  public void teardown() {
    reporter.failIfPendingErrors();
  }

  private R8TestCompileResult compileApplicationWithR8(StringConsumer keepRuleConsumer)
      throws IOException, CompilationFailedException {
    return compileApplicationWithR8(keepRuleConsumer, ThrowableConsumer.empty());
  }

  private R8TestCompileResult compileApplicationWithR8(
      StringConsumer keepRuleConsumer, ThrowableConsumer<R8FullTestBuilder> configuration)
      throws IOException, CompilationFailedException {
    return testForR8(parameters.getBackend())
        .addProgramFiles(getProgramFiles())
        .addLibraryFiles(getLibraryFiles())
        .addKeepRuleFiles(getKeepRuleFiles())
        .addDontWarn("android.app.Activity$TranslucentConversionListener")
        .allowDiagnosticMessages()
        .allowUnusedDontWarnPatterns()
        .allowUnusedProguardConfigurationRules()
        .apply(configuration)
        .setMinApi(getApiLevel())
        .enableCoreLibraryDesugaring(
            getApiLevel(),
            keepRuleConsumer,
            StringResource.fromFile(getDesugaredLibraryConfiguration()))
        .compile()
        .assertAllInfoMessagesMatch(
            anyOf(
                containsString("Ignoring option: -optimizations"),
                containsString("Proguard configuration rule does not match anything"),
                containsString("Invalid signature")))
        .apply(this::printProtoStats);
  }

  private L8TestCompileResult compileDesugaredLibraryWithL8(KeepRuleConsumer keepRuleConsumer)
      throws CompilationFailedException, IOException, ExecutionException {
    return testForL8(getApiLevel())
        .setDesugaredLibraryConfiguration(getDesugaredLibraryConfiguration())
        .setDesugarJDKLibs(getDesugaredLibraryJDKLibs())
        .setDesugarJDKLibsConfiguration(getDesugaredLibraryJDKLibsConfiguration())
        .addGeneratedKeepRules(keepRuleConsumer.get())
        .addKeepRuleFiles(getDesugaredLibraryKeepRuleFiles())
        .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
        .compile();
  }

  private void inspect(R8TestCompileResult r8CompileResult, L8TestCompileResult l8CompileResult)
      throws IOException, ResourceException {
    r8CompileResult.runDex2Oat(parameters.getRuntime()).assertNoVerificationErrors();
    l8CompileResult.runDex2Oat(parameters.getRuntime()).assertNoVerificationErrors();

    int applicationSize = r8CompileResult.getApp().applicationSize();
    if (applicationSize > MAX_APPLICATION_SIZE) {
      reporter.error(
          "Expected application size to be <="
              + MAX_APPLICATION_SIZE
              + ", but was "
              + applicationSize);
    }

    int desugaredLibrarySize = l8CompileResult.getApp().applicationSize();
    if (desugaredLibrarySize > MAX_DESUGARED_LIBRARY_SIZE) {
      reporter.error(
          "Expected desugared library size to be <="
              + MAX_DESUGARED_LIBRARY_SIZE
              + ", but was "
              + desugaredLibrarySize);
    }

    if (isLocalDevelopment()) {
      System.out.println("Dex size (application, excluding desugared library): " + applicationSize);
      System.out.println("Dex size (desugared library): " + desugaredLibrarySize);
      System.out.println("Dex size (total): " + (applicationSize + desugaredLibrarySize));
    }
  }

  private void dump(R8TestCompileResult r8CompileResult, L8TestCompileResult l8CompileResult)
      throws IOException {
    assertTrue(isLocalDevelopment());
    Files.createDirectories(dumpDirectory);
    r8CompileResult
        .writeToDirectory(dumpDirectory)
        .writeProguardMap(dumpDirectory.resolve("mapping.txt"));
    l8CompileResult
        .writeSingleDexOutputToFile(dumpDirectory.resolve("classes5.dex"))
        .writeGeneratedKeepRules(dumpDirectory.resolve("l8-keep.txt"))
        .writeProguardMap(dumpDirectory.resolve("l8-mapping.txt"));
  }
}
