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

import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
import static com.android.tools.r8.shaking.ProguardConfigurationParser.REPACKAGE_CLASSES;
import static org.hamcrest.CoreMatchers.containsString;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.ImmutableList;
import java.util.List;
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 RepackageParameterSyntheticOutlineTest extends RepackageTestBase {

  private final String NEW_DESCRIPTOR = "Lfoo/ClassWithCodeToBeOutlined;";
  private final String[] EXPECTED =
      new String[] {"Param::testParam", "Return::print", "Param::testParam", "Return::print"};

  @Parameters(name = "{1}, kind: {0}")
  public static List<Object[]> data() {
    return buildParameters(
        ImmutableList.of(REPACKAGE_CLASSES), // Repackage will use foo as the package name.
        getTestParameters().withDexRuntimes().withAllApiLevels().build());
  }

  public RepackageParameterSyntheticOutlineTest(
      String flattenPackageHierarchyOrRepackageClasses, TestParameters parameters) {
    super(flattenPackageHierarchyOrRepackageClasses, parameters);
  }

  @Test
  public void testRuntime() throws Exception {
    testForRuntime(parameters)
        .addProgramClasses(Param.class, Return.class)
        .addProgramClassFileData(
            rewrittenPackageForClassWithCodeToBeOutlined(),
            rewrittenMainWithMethodReferencesToCodeToBeOutlined())
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutputLines(EXPECTED);
  }

  @Test(expected = CompilationFailedException.class)
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .addProgramClasses(Param.class, Return.class)
        .addProgramClassFileData(
            rewrittenPackageForClassWithCodeToBeOutlined(),
            rewrittenMainWithMethodReferencesToCodeToBeOutlined())
        .addKeepMainRule(Main.class)
        .addKeepClassRulesWithAllowObfuscation(Param.class, Return.class)
        .setMinApi(parameters.getApiLevel())
        .enableInliningAnnotations()
        .addOptionsModification(
            options -> {
              options.outline.minSize = 2;
              options.outline.threshold = 2;
            })
        .apply(this::configureRepackaging)
        .addKeepPackageNamesRule("bar**")
        .compileWithExpectedDiagnostics(
            diagnostics -> {
              // TODO(b/180092122): This should not fail.
              diagnostics.assertErrorsMatch(
                  diagnosticMessage(
                      containsString("The synthetic method reference should have moved")));
            });
  }

  private byte[] rewrittenPackageForClassWithCodeToBeOutlined() throws Exception {
    return transformer(ClassWithCodeToBeOutlined.class)
        .setClassDescriptor(NEW_DESCRIPTOR)
        .transform();
  }

  private byte[] rewrittenMainWithMethodReferencesToCodeToBeOutlined() throws Exception {
    return transformer(Main.class)
        .replaceClassDescriptorInMethodInstructions(
            DescriptorUtils.javaTypeToDescriptor(ClassWithCodeToBeOutlined.class.getTypeName()),
            NEW_DESCRIPTOR)
        .transform();
  }

  // Will be renamed by repackaging
  public static class Param {

    @NeverInline
    public void testParam() {
      System.out.println("Param::testParam");
    }

    @NeverInline
    public Return getReturn() {
      return new Return();
    }
  }

  // Will be renamed by repackaging
  public static class Return {

    public void print() {
      System.out.println("Return::print");
    }
  }

  // Renamed to baz.ClassWithCodeToBeOutlined such that we can keep this package name.
  public static class ClassWithCodeToBeOutlined {

    @NeverInline
    public static Return foo(Param param) {
      param.testParam();
      return param.getReturn();
    }

    @NeverInline
    public static Return bar(Param param) {
      param.testParam();
      return param.getReturn();
    }
  }

  public static class Main {

    public static void main(String[] args) {
      Param param = new Param();
      ClassWithCodeToBeOutlined.foo(param).print();
      ClassWithCodeToBeOutlined.bar(param).print();
    }
  }
}
