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

import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.AndroidApiLevel;
import java.util.List;
import java.util.Objects;
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 NullCheckEnumUnboxingTest extends EnumUnboxingTestBase {

  private final TestParameters parameters;
  private final boolean enumValueOptimization;
  private final EnumKeepRules enumKeepRules;

  @Parameters(name = "{0} valueOpt: {1} keep: {2}")
  public static List<Object[]> data() {
    return enumUnboxingTestParameters();
  }

  public NullCheckEnumUnboxingTest(
      TestParameters parameters, boolean enumValueOptimization, EnumKeepRules enumKeepRules) {
    this.parameters = parameters;
    this.enumValueOptimization = enumValueOptimization;
    this.enumKeepRules = enumKeepRules;
  }

  @Test
  public void testEnumUnboxing() throws Exception {
    R8TestRunResult run =
        testForR8(parameters.getBackend())
            .addInnerClasses(NullCheckEnumUnboxingTest.class)
            .addKeepMainRule(MainNullTest.class)
            .addKeepRules(enumKeepRules.getKeepRules())
            .enableNeverClassInliningAnnotations()
            .enableInliningAnnotations()
            .addOptionsModification(opt -> enableEnumOptions(opt, enumValueOptimization))
            .allowDiagnosticMessages()
            .setMinApi(parameters.getApiLevel())
            .compile()
            .inspectDiagnosticMessages(
                m -> {
                  assertEnumIsUnboxed(MyEnum.class, MyEnum.class.getSimpleName(), m);
                  // MyEnum19 is unboxed only if minAPI > 19 because Objects#requiredNonNull is then
                  // present.
                  if (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.K)) {
                    assertEnumIsUnboxed(MyEnum19.class, MyEnum19.class.getSimpleName(), m);
                  } else {
                    assertEnumIsBoxed(MyEnum19.class, MyEnum19.class.getSimpleName(), m);
                  }
                })
            .run(parameters.getRuntime(), MainNullTest.class)
            .assertSuccess();
    assertLines2By2Correct(run.getStdOut());
  }

  @NeverClassInline
  enum MyEnum {
    A,
    B,
    C
  }

  @NeverClassInline
  enum MyEnum19 {
    A,
    B,
    C
  }

  static class MainNullTest {

    public static void main(String[] args) {
      nullCheckTests();
      nullCheckMessageTests();
    }

    private static void nullCheckTests() {
      nullCheck0Test(MyEnum.A, false);
      nullCheck0Test(MyEnum.B, false);
      nullCheck0Test(null, true);

      nullCheck1Test(MyEnum.A, false);
      nullCheck1Test(MyEnum.B, false);
      nullCheck1Test(null, true);

      nullCheck2Test(MyEnum19.A, false);
      nullCheck2Test(MyEnum19.B, false);
      nullCheck2Test(null, true);
    }

    private static void nullCheckMessageTests() {
      nullCheckMessage0Test(MyEnum.A, "myMessageA", false);
      nullCheckMessage0Test(MyEnum.B, "myMessageB", false);
      nullCheckMessage0Test(null, "myMessageN", true);

      nullCheckMessage1Test(MyEnum19.A, "myMessageA", false);
      nullCheckMessage1Test(MyEnum19.B, "myMessageB", false);
      nullCheckMessage1Test(null, "myMessageN", true);
    }

    private static void nullCheck0Test(MyEnum input, boolean isNull) {
      String result = "pass";
      try {
        nullCheck0(input);
      } catch (NullPointerException ex8) {
        result = "fail";
      }
      System.out.println(result);
      System.out.println(isNull ? "fail" : "pass");
    }

    private static void nullCheck1Test(MyEnum input, boolean isNull) {
      String result = "pass";
      try {
        nullCheck1(input);
      } catch (NullPointerException ex8) {
        result = "fail";
      }
      System.out.println(result);
      System.out.println(isNull ? "fail" : "pass");
    }

    private static void nullCheck2Test(MyEnum19 input, boolean isNull) {
      String result = "pass";
      try {
        nullCheck2(input);
      } catch (NullPointerException ex) {
        result = "fail";
      }
      System.out.println(result);
      System.out.println(isNull ? "fail" : "pass");
    }

    private static void nullCheckMessage0Test(MyEnum input, String message, boolean isNull) {
      String result = "pass";
      try {
        nullCheckMessage0(input, message);
      } catch (NullPointerException ex) {
        result = ex.getMessage();
      }
      System.out.println(result);
      System.out.println(isNull ? message : "pass");
    }

    private static void nullCheckMessage1Test(MyEnum19 input, String message, boolean isNull) {
      String result = "pass";
      try {
        nullCheckMessage1(input, message);
      } catch (NullPointerException ex) {
        result = ex.getMessage();
      }
      System.out.println(result);
      System.out.println(isNull ? message : "pass");
    }

    @NeverInline
    private static void nullCheck0(MyEnum e) {
      if (e == null) {
        throw new NullPointerException();
      }
    }

    @SuppressWarnings("ResultOfMethodCallIgnored")
    @NeverInline
    private static void nullCheck1(MyEnum e) {
      e.getClass();
    }

    @NeverInline
    private static void nullCheck2(MyEnum19 e) {
      Objects.requireNonNull(e);
    }

    @NeverInline
    private static void nullCheckMessage0(MyEnum e, String message) {
      if (e == null) {
        throw new NullPointerException(message);
      }
    }

    @NeverInline
    private static void nullCheckMessage1(MyEnum19 e, String message) {
      Objects.requireNonNull(e, message);
    }
  }
}
