// Copyright (c) 2024, 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 switchpatternmatching;

import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.desugarMatchException;
import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.hasJdk21EnumSwitch;
import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.hasJdk21TypeSwitch;
import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.matchException;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.JdkClassFileProvider;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

// This test is copied into later JDK tests (currently JDK-23). The reason for the copy is that
// from JDK-23 the code generation changed. Please update the copy as well if updating this test.
@RunWith(Parameterized.class)
public class EnumMoreCasesAtRuntimeSwitchTest extends TestBase {

  @Parameter public TestParameters parameters;

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters()
        .withCfRuntimesStartingFromIncluding(CfVm.JDK21)
        .withDexRuntimes()
        .withAllApiLevelsAlsoForCf()
        .build();
  }

  public static String EXPECTED_OUTPUT =
      StringUtils.lines(
          "TYPE",
          "null",
          "E1",
          "class %s",
          "E3",
          "class %s",
          "E5",
          "a C",
          "ENUM",
          "null",
          "1",
          "0",
          "3",
          "4",
          "0");

  @Test
  public void testJvm() throws Exception {
    assumeTrue(parameters.isCfRuntime());
    CodeInspector inspector = new CodeInspector(ToolHelper.getClassFileForTestClass(Main.class));
    assertTrue(
        hasJdk21EnumSwitch(inspector.clazz(Main.class).uniqueMethodWithOriginalName("enumSwitch")));
    assertTrue(
        hasJdk21TypeSwitch(inspector.clazz(Main.class).uniqueMethodWithOriginalName("typeSwitch")));

    parameters.assumeJvmTestParameters();
    testForJvm(parameters)
        .apply(this::addModifiedProgramClasses)
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutput(
            String.format(EXPECTED_OUTPUT, matchException(), matchException()));
  }

  private <T extends TestBuilder<?, T>> void addModifiedProgramClasses(
      TestBuilder<?, T> testBuilder) throws Exception {
    testBuilder
        .addStrippedOuter(getClass())
        .addProgramClasses(FakeI.class, C.class, I.class)
        .addProgramClassFileData(
            transformer(CompileTimeE.class)
                .setImplements(FakeI.class)
                .setClassDescriptor(RuntimeE.class.descriptorString())
                .transform())
        .addProgramClassFileData(
            transformer(RuntimeE.class)
                .setImplements(I.class)
                .setClassDescriptor(CompileTimeE.class.descriptorString())
                .transform())
        .addProgramClassFileData(
            transformer(Main.class)
                .transformFieldInsnInMethod(
                    "getE2",
                    (opcode, owner, name, descriptor, visitor) -> {
                      visitor.visitFieldInsn(opcode, owner, "E2", descriptor);
                    })
                .transformFieldInsnInMethod(
                    "getE4",
                    (opcode, owner, name, descriptor, visitor) -> {
                      visitor.visitFieldInsn(opcode, owner, "E4", descriptor);
                    })
                .transform());
  }

  @Test
  public void testD8() throws Exception {
    testForD8(parameters.getBackend())
        .apply(this::addModifiedProgramClasses)
        .setMinApi(parameters)
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutput(
            String.format(EXPECTED_OUTPUT, desugarMatchException(), desugarMatchException()));
  }

  @Test
  public void testR8() throws Exception {
    parameters.assumeR8TestParameters();
    testForR8(parameters.getBackend())
        .apply(this::addModifiedProgramClasses)
        .applyIf(
            parameters.isCfRuntime(),
            b -> b.addLibraryProvider(JdkClassFileProvider.fromSystemJdk()))
        .setMinApi(parameters)
        .addKeepMainRule(Main.class)
        .addKeepEnumsRule()
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutput(
            String.format(EXPECTED_OUTPUT, matchException(parameters), matchException(parameters)));
  }

  sealed interface I permits CompileTimeE, C {}

  public enum RuntimeE implements FakeI {
    E1,
    E2, // Case present at runtime.
    E3,
    E4, // Case present at runtime.
    E5
  }

  interface FakeI {}

  public enum CompileTimeE implements I {
    E1,
    E3,
    E5
  }

  static final class C implements I {}

  static class Main {

    static void typeSwitch(I i) {
      switch (i) {
        case CompileTimeE.E1 -> {
          System.out.println("E1");
        }
        case CompileTimeE.E3 -> {
          System.out.println("E3");
        }
        case CompileTimeE.E5 -> {
          System.out.println("E5");
        }
        case C c -> {
          System.out.println("a C");
        }
      }
    }

    static void enumSwitch(CompileTimeE e) {
      switch (e) {
        case null -> System.out.println("null");
        case CompileTimeE.E1 -> System.out.println("1");
        case CompileTimeE t when t == CompileTimeE.E3 -> System.out.println("3");
        case CompileTimeE t when t.name().equals("E4") ->
            System.out.println("4"); // Case present at runtime.
        case CompileTimeE t -> System.out.println("0");
      }
    }

    public static CompileTimeE getE2() {
      // Replaced by RuntimeE.E2;
      return CompileTimeE.E1;
    }

    public static CompileTimeE getE4() {
      // Replaced by RuntimeE.E4;
      return CompileTimeE.E1;
    }

    public static void main(String[] args) {
      System.out.println("TYPE");
      try {
        typeSwitch(null);
      } catch (NullPointerException e) {
        System.out.println("null");
      }
      typeSwitch(CompileTimeE.E1);
      try {
        typeSwitch(getE2());
      } catch (Exception e) {
        System.out.println(e.getClass().toString());
      }
      typeSwitch(CompileTimeE.E3);
      try {
        typeSwitch(getE4());
      } catch (Exception e) {
        System.out.println(e.getClass().toString());
      }
      typeSwitch(CompileTimeE.E5);
      typeSwitch(new C());

      System.out.println("ENUM");
      enumSwitch(null);
      enumSwitch(CompileTimeE.E1);
      enumSwitch(getE2());
      enumSwitch(CompileTimeE.E3);
      enumSwitch(getE4());
      enumSwitch(CompileTimeE.E5);
    }
  }
}
