// 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 org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import static switchpatternmatching.SwitchTestHelper.desugarMatchException;
import static switchpatternmatching.SwitchTestHelper.hasJdk21EnumSwitch;
import static switchpatternmatching.SwitchTestHelper.hasJdk21TypeSwitch;
import static switchpatternmatching.SwitchTestHelper.matchException;

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.Assume;
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;

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

  @Parameter public TestParameters parameters;

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimes().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)
        .applyIf(
            parameters.getCfRuntime().isNewerThanOrEqual(CfVm.JDK21),
            r ->
                r.assertSuccessWithOutput(
                    String.format(EXPECTED_OUTPUT, matchException(), matchException())),
            r -> r.assertFailureWithErrorThatThrows(UnsupportedClassVersionError.class));
  }

  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();
    Assume.assumeTrue(
        parameters.isDexRuntime()
            || (parameters.isCfRuntime()
                && parameters.getCfRuntime().isNewerThanOrEqual(CfVm.JDK21)));
    testForR8(parameters.getBackend())
        .apply(this::addModifiedProgramClasses)
        .applyIf(
            parameters.isCfRuntime(),
            b -> b.addLibraryProvider(JdkClassFileProvider.fromSystemJdk()))
        .setMinApi(parameters)
        .addKeepMainRule(Main.class)
        .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);
    }
  }
}
