// 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 YouTubeV1620Test extends YouTubeCompilationTestBase {

  private static final int MAX_APPLICATION_SIZE = 29750000;
  private static final int MAX_DESUGARED_LIBRARY_SIZE = 425000;

  private final TestParameters parameters;

  private final Path dumpDirectory = Paths.get("YouTubeV1620-" + 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 YouTubeV1620Test(TestParameters parameters) {
    super(16, 20, 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())
        .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"));
  }
}
