// Copyright (c) 2019, 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.desugar.desugaredlibrary;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;

import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NoVerticalClassMerging;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestCompileResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.ThrowingSupplier;
import com.android.tools.r8.utils.codeinspector.CheckCastInstructionSubject;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.CodeMatchers;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.InvokeInstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.android.tools.r8.utils.codeinspector.TryCatchSubject;
import com.android.tools.r8.utils.codeinspector.TypeSubject;
import com.google.common.collect.ImmutableSet;
import java.nio.file.Path;
import java.time.DateTimeException;
import java.time.ZoneId;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
import java.time.temporal.TemporalQueries;
import java.time.temporal.TemporalQuery;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Assume;
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 JavaTimeTest extends DesugaredLibraryTestBase {

  private final TestParameters parameters;
  private final boolean shrinkDesugaredLibrary;
  private final boolean traceReferencesKeepRules;
  private static final String expectedOutput =
      StringUtils.lines(
          "Caught java.time.format.DateTimeParseException",
          "true",
          "1970-01-02T10:17:36.789Z",
          "GMT",
          "GMT",
          "true",
          "true",
          "Hello, world");

  @Parameters(name = "{2}, shrinkDesugaredLibrary: {0}, traceReferencesKeepRules {1}")
  public static List<Object[]> data() {
    return buildParameters(
        BooleanUtils.values(),
        BooleanUtils.values(),
        getTestParameters()
            .withAllRuntimes()
            .withAllApiLevelsAlsoForCf()
            .withApiLevel(AndroidApiLevel.N)
            .build());
  }

  public JavaTimeTest(
      boolean shrinkDesugaredLibrary, boolean traceReferencesKeepRules, TestParameters parameters) {
    this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
    this.traceReferencesKeepRules = traceReferencesKeepRules;
    this.parameters = parameters;
  }

  private void checkRewrittenInvokesForD8(CodeInspector inspector) {
    checkRewrittenInvokes(inspector, false);
  }

  private void checkRewrittenInvokesForR8(CodeInspector inspector) {
    checkRewrittenInvokes(inspector, true);
  }

  private void checkRewrittenInvokes(CodeInspector inspector, boolean isR8) {
    Set<String> expectedInvokeHolders;
    Set<String> expectedCatchGuards;
    Set<String> expectedCheckCastType;
    String expectedInstanceOfTypes;
    if (parameters.getApiLevel().getLevel() >= 26) {
      expectedInvokeHolders =
          ImmutableSet.of(
              "java.time.Clock", "java.time.LocalDate", "java.time.ZoneOffset", "java.time.ZoneId");
      expectedCatchGuards = ImmutableSet.of("java.time.format.DateTimeParseException");
      expectedCheckCastType = ImmutableSet.of("java.time.ZoneId");
      expectedInstanceOfTypes = "java.time.ZoneOffset";
    } else {
      expectedInvokeHolders =
          ImmutableSet.of(
              "j$.time.Clock", "j$.time.LocalDate", "j$.time.ZoneOffset", "j$.time.ZoneId");
      expectedCatchGuards = ImmutableSet.of("j$.time.format.DateTimeParseException");
      expectedCheckCastType = ImmutableSet.of("j$.time.ZoneId");
      expectedInstanceOfTypes = "j$.time.ZoneOffset";
    }
    ClassSubject classSubject = inspector.clazz(TestClass.class);
    assertThat(classSubject, isPresent());
    MethodSubject main = classSubject.uniqueMethodWithName("main");
    Set<String> foundInvokeHolders =
        main.streamInstructions()
            .filter(InstructionSubject::isInvoke)
            .map(
                instructionSubject ->
                    ((InvokeInstructionSubject) instructionSubject).holder().toString())
            .filter(holder -> holder.startsWith("j$.time.") || holder.startsWith("java.time."))
            .collect(Collectors.toSet());
    assertEquals(expectedInvokeHolders, foundInvokeHolders);
    main.streamInstructions()
        .filter(InstructionSubject::isCheckCast)
        .map(InstructionSubject::asCheckCast)
        .map(CheckCastInstructionSubject::getType)
        .map(DexType::toSourceString)
        .collect(Collectors.toSet())
        .equals(expectedCheckCastType);
    assertEquals(
        1,
        main.streamInstructions().filter(io -> io.isInstanceOf(expectedInstanceOfTypes)).count());

    Set<String> foundCatchGuards =
        main.streamTryCatches()
            .flatMap(TryCatchSubject::streamGuards)
            .map(TypeSubject::toString)
            .collect(Collectors.toSet());
    assertEquals(expectedCatchGuards, foundCatchGuards);

    if (isR8) {
      assertThat(
          inspector.clazz(TemporalAccessorImpl.class).uniqueMethodWithFinalName("query"),
          not(isPresent()));
    } else {
      assertThat(
          inspector.clazz(TemporalAccessorImplSub.class).uniqueMethodWithFinalName("query"),
          CodeMatchers.invokesMethod(
              null, TemporalAccessorImpl.class.getTypeName(), "query", null));
    }
    if (parameters
        .getApiLevel()
        .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport())) {
      assertThat(
          inspector.clazz(TemporalAccessorImpl.class).uniqueMethodWithName("query"),
          not(isPresent()));
    } else {
      assertThat(
          inspector
              .clazz(isR8 ? TemporalAccessorImplSub.class : TemporalAccessorImpl.class)
              .uniqueMethodWithFinalName("query"),
          CodeMatchers.invokesMethod(
              null, "j$.time.temporal.TemporalAccessor$-CC", "$default$query", null));
    }
  }

  private String desugaredLibraryKeepRules(
      KeepRuleConsumer keepRuleConsumer, ThrowingSupplier<Path, Exception> programSupplier)
      throws Exception {
    String desugaredLibraryKeepRules = null;
    if (shrinkDesugaredLibrary) {
      desugaredLibraryKeepRules = keepRuleConsumer.get();
      if (desugaredLibraryKeepRules != null) {
        if (traceReferencesKeepRules) {
          desugaredLibraryKeepRules =
              collectKeepRulesWithTraceReferences(
                  programSupplier.get(), buildDesugaredLibraryClassFile(parameters.getApiLevel()));
        }
      }
    }
    return desugaredLibraryKeepRules;
  }

  @Test
  public void testTimeD8Cf() throws Exception {
    Assume.assumeTrue(shrinkDesugaredLibrary || !traceReferencesKeepRules);

    KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
    // Use D8 to desugar with Java classfile output.
    Path jar =
        testForD8(Backend.CF)
            .addInnerClasses(JavaTimeTest.class)
            .setMinApi(parameters.getApiLevel())
            .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
            .compile()
            .inspect(this::checkRewrittenInvokesForD8)
            .writeToZip();

    String desugaredLibraryKeepRules;
    if (shrinkDesugaredLibrary && !traceReferencesKeepRules && keepRuleConsumer.get() != null) {
      // Collection keep rules is only implemented in the DEX writer.
      assertEquals(0, keepRuleConsumer.get().length());
      desugaredLibraryKeepRules = "-keep class * { *; }";
    } else {
      desugaredLibraryKeepRules = desugaredLibraryKeepRules(keepRuleConsumer, () -> jar);
    }

    // Determine desugared library keep rules.
    if (parameters.getRuntime().isDex()) {
      // Convert to DEX without desugaring and run.
      testForD8()
          .addProgramFiles(jar)
          .setMinApi(parameters.getApiLevel())
          .disableDesugaring()
          .compile()
          .addDesugaredCoreLibraryRunClassPath(
              this::buildDesugaredLibrary,
              parameters.getApiLevel(),
              desugaredLibraryKeepRules,
              shrinkDesugaredLibrary)
          .run(parameters.getRuntime(), TestClass.class)
          .assertSuccessWithOutput(expectedOutput);
    } else {
      // Run on the JVM with desugared library on classpath.
      testForJvm()
          .addProgramFiles(jar)
          .addRunClasspathFiles(buildDesugaredLibraryClassFile(parameters.getApiLevel()))
          .run(parameters.getRuntime(), TestClass.class)
          .assertSuccessWithOutput(expectedOutput);
    }
  }

  @Test
  public void testTimeD8() throws Exception {
    Assume.assumeTrue(parameters.getRuntime().isDex());
    Assume.assumeTrue(shrinkDesugaredLibrary || !traceReferencesKeepRules);

    KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
    TestCompileResult<?, ?> result =
        testForD8()
            .addInnerClasses(JavaTimeTest.class)
            .setMinApi(parameters.getApiLevel())
            .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
            .compile()
            .inspect(this::checkRewrittenInvokesForD8);
    result
        .addDesugaredCoreLibraryRunClassPath(
            this::buildDesugaredLibrary,
            parameters.getApiLevel(),
            desugaredLibraryKeepRules(keepRuleConsumer, result::writeToZip),
            shrinkDesugaredLibrary)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(expectedOutput);
  }

  @Test
  public void testTimeR8() throws Exception {
    Assume.assumeTrue(parameters.getRuntime().isDex());
    Assume.assumeTrue(shrinkDesugaredLibrary || !traceReferencesKeepRules);

    KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
    TestCompileResult<?, ?> result =
        testForR8(parameters.getBackend())
            .addInnerClasses(JavaTimeTest.class)
            .addKeepMainRule(TestClass.class)
            .applyIf(
                parameters.getApiLevel().isLessThan(AndroidApiLevel.O),
                builder -> builder.addDontWarnRetargetLibraryMembers())
            .enableNoVerticalClassMergingAnnotations()
            .setMinApi(parameters.getApiLevel())
            .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
            .enableInliningAnnotations()
            .compile()
            .inspect(this::checkRewrittenInvokesForR8);
    result
        .addDesugaredCoreLibraryRunClassPath(
            this::buildDesugaredLibrary,
            parameters.getApiLevel(),
            desugaredLibraryKeepRules(keepRuleConsumer, result::writeToZip),
            shrinkDesugaredLibrary)
        .run(parameters.getRuntime(), TestClass.class)
        .assertSuccessWithOutput(expectedOutput);
  }

  @NoVerticalClassMerging
  static class TemporalAccessorImpl implements TemporalAccessor {
    @Override
    public boolean isSupported(TemporalField field) {
      return false;
    }

    @Override
    public long getLong(TemporalField field) {
      throw new DateTimeException("Mock");
    }
  }

  @NoVerticalClassMerging
  static class TemporalAccessorImplSub extends TemporalAccessorImpl {
    @SuppressWarnings("unchecked")
    @Override
    public <R> R query(TemporalQuery<R> query) {
      if (query == TemporalQueries.zoneId()) {
        return (R) ZoneId.of("GMT");
      }
      return super.query(query);
    }
  }

  static class TestClass {

    @NeverInline
    public static Object newObjectInstance() {
      return System.currentTimeMillis() > 0 ? new Object() : null;
    }

    @NeverInline
    public static Object nullReference() {
      return System.currentTimeMillis() > 0 ? null : new Object();
    }

    public static void superInvokeOnLibraryDesugaredDefaultMethod() {
      TemporalAccessor mock =
          new TemporalAccessor() {
            @Override
            public boolean isSupported(TemporalField field) {
              return false;
            }

            @Override
            public long getLong(TemporalField field) {
              throw new DateTimeException("Mock");
            }

            @SuppressWarnings("unchecked")
            @Override
            public <R> R query(TemporalQuery<R> query) {
              if (query == TemporalQueries.zoneId()) {
                return (R) ZoneId.of("GMT");
              }
              return TemporalAccessor.super.query(query);
            }
          };
      System.out.println(ZoneId.from(mock).equals(ZoneId.of("GMT")));
    }

    public static void superInvokeOnLibraryDesugaredDefaultMethodFromSubclass() {
      TemporalAccessor mock = new TemporalAccessorImplSub();
      System.out.println(ZoneId.from(mock).equals(ZoneId.of("GMT")));
    }

    public static void main(String[] args) {
      java.time.Clock.systemDefaultZone();
      try {
        java.time.LocalDate.parse("");
      } catch (java.time.format.DateTimeParseException e) {
        System.out.println("Caught java.time.format.DateTimeParseException");
      }
      java.time.ZoneId id = (java.time.ZoneId) nullReference();
      if (newObjectInstance() instanceof java.time.ZoneOffset) {
        System.out.println("NOT!");
      }
      System.out.println(java.time.ZoneOffset.getAvailableZoneIds().size() > 0);

      System.out.println(
          java.util.Date.from(new java.util.Date(123456789).toInstant()).toInstant());

      java.util.TimeZone timeZone = java.util.TimeZone.getTimeZone(java.time.ZoneId.of("GMT"));
      System.out.println(timeZone.getID());
      System.out.println(timeZone.toZoneId().getId());

      superInvokeOnLibraryDesugaredDefaultMethod();
      superInvokeOnLibraryDesugaredDefaultMethodFromSubclass();

      System.out.println("Hello, world");
    }
  }
}
