// 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.desugar.desugaredlibrary;

import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.fail;
import static org.hamcrest.CoreMatchers.containsString;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.ZipUtils;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
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 IteratorTest extends DesugaredLibraryTestBase {

  private final TestParameters parameters;
  private final boolean shrinkDesugaredLibrary;
  private final boolean canUseDefaultAndStaticInterfaceMethods;

  private static final String EXPECTED_OUTPUT = StringUtils.lines("1", "2", "3");

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

  public IteratorTest(boolean shrinkDesugaredLibrary, TestParameters parameters) {
    this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
    this.parameters = parameters;
    this.canUseDefaultAndStaticInterfaceMethods =
        parameters
            .getApiLevel()
            .isGreaterThanOrEqualTo(apiLevelWithDefaultInterfaceMethodsSupport());
  }

  @Test
  public void testIterator() throws Exception {
    if (parameters.isCfRuntime()) {
      testForJvm()
          .addInnerClasses(IteratorTest.class)
          .run(parameters.getRuntime(), Main.class)
          .assertSuccessWithOutput(EXPECTED_OUTPUT);
      return;
    }
    KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
    testForD8()
        .addInnerClasses(IteratorTest.class)
        .setMinApi(parameters.getApiLevel())
        .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
        .compile()
        .addDesugaredCoreLibraryRunClassPath(
            this::buildDesugaredLibrary,
            parameters.getApiLevel(),
            keepRuleConsumer.get(),
            shrinkDesugaredLibrary)
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutput(EXPECTED_OUTPUT);
  }

  @Test
  public void testD8Cf() throws Exception {
    // Use D8 to desugar with Java classfile output.
    Path firstJar =
        testForD8(Backend.CF)
            .setMinApi(parameters.getApiLevel())
            .addProgramClasses(Main.class, MyIterator.class)
            .enableCoreLibraryDesugaring(parameters.getApiLevel(), new AbsentKeepRuleConsumer())
            .compile()
            .writeToZip();

    ClassFileInfo info =
        extractClassFileInfo(
            ZipUtils.readSingleEntry(firstJar, ZipUtils.zipEntryNameForClass(MyIterator.class)));
    assertEquals(
        MyIterator.class.getTypeName(),
        DescriptorUtils.getJavaTypeFromBinaryName(info.getClassBinaryName()));
    assertEquals(
        canUseDefaultAndStaticInterfaceMethods ? 0 : 1,
        info.getInterfaces().stream().filter(name -> name.equals("j$/util/Iterator")).count());
    assertEquals(
        canUseDefaultAndStaticInterfaceMethods ? 1 : 2,
        info.getMethodNames().stream().filter(name -> name.equals("forEachRemaining")).count());

    AndroidApiLevel apiLevelNotRequiringDesugaring = AndroidApiLevel.N;
    if (parameters.getApiLevel().isLessThan(apiLevelNotRequiringDesugaring)) {
      try {
        // Use D8 to desugar with Java classfile output.
        testForD8(Backend.CF)
            .setMinApi(parameters.getApiLevel())
            .addProgramFiles(firstJar)
            .enableCoreLibraryDesugaring(parameters.getApiLevel(), new AbsentKeepRuleConsumer())
            .compileWithExpectedDiagnostics(
                diagnostics ->
                    diagnostics.assertErrorsMatch(
                        diagnosticMessage(
                            containsString(
                                "Code has already been library desugared. "
                                    + "Interface Lj$/util/Iterator; is already implemented by "
                                    + "Lcom/android/tools/r8/desugar/desugaredlibrary/"
                                    + "IteratorTest$MyIterator;"))));
        fail("Expected failure");
      } catch (CompilationFailedException e) {
        // Expected.
      }
    }

    // Use D8 to desugar with Java classfile output.
    Path secondJar =
        testForD8(Backend.CF)
            .addOptionsModification(
                options ->
                    options.desugarSpecificOptions().allowAllDesugaredInput =
                        parameters.getApiLevel().isLessThan(apiLevelNotRequiringDesugaring))
            .setMinApi(parameters.getApiLevel())
            .addProgramFiles(firstJar)
            .enableCoreLibraryDesugaring(parameters.getApiLevel(), new AbsentKeepRuleConsumer())
            .compile()
            .writeToZip();

    info =
        extractClassFileInfo(
            ZipUtils.readSingleEntry(secondJar, ZipUtils.zipEntryNameForClass(MyIterator.class)));
    assertEquals(
        MyIterator.class.getTypeName(),
        DescriptorUtils.getJavaTypeFromBinaryName(info.getClassBinaryName()));
    assertEquals(
        canUseDefaultAndStaticInterfaceMethods ? 0 : 1,
        info.getInterfaces().stream().filter(name -> name.equals("j$/util/Iterator")).count());
    assertEquals(
        canUseDefaultAndStaticInterfaceMethods ? 1 : 2,
        info.getMethodNames().stream().filter(name -> name.equals("forEachRemaining")).count());

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

  static class Main {

    public static void main(String[] args) {
      Iterator<Integer> iterator = new MyIterator<>(1, 2, 3);
      iterator.forEachRemaining(System.out::println);
    }
  }

  static class MyIterator<E> implements Iterator<E> {

    int index;
    E[] items;

    @SafeVarargs
    public MyIterator(E... items) {
      this.items = items;
    }

    @Override
    public boolean hasNext() {
      return index < items.length;
    }

    @Override
    public E next() {
      return items[index++];
    }

    @Override
    public void forEachRemaining(Consumer<? super E> action) {
      while (hasNext()) {
        action.accept(next());
      }
    }
  }
}
