// 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.corelib.conversionTests;

import static junit.framework.TestCase.assertEquals;

import com.android.tools.r8.TestRuntime.DexRuntime;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
import java.nio.file.Path;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.BooleanSupplier;
import java.util.function.DoublePredicate;
import java.util.function.DoubleSupplier;
import java.util.function.Function;
import java.util.function.IntSupplier;
import java.util.function.LongConsumer;
import java.util.function.LongSupplier;
import java.util.stream.Collectors;
import org.junit.Test;

public class FunctionConversionTest extends APIConversionTestBase {

  @Test
  public void testFunctionComposition() throws Exception {
    Path customLib = testForD8().addProgramClasses(CustomLibClass.class).compile().writeToZip();
    testForD8()
        .setMinApi(AndroidApiLevel.B)
        .addProgramClasses(
            Executor.class, Executor.Object1.class, Executor.Object2.class, Executor.Object3.class)
        .addLibraryClasses(CustomLibClass.class)
        .enableCoreLibraryDesugaring(AndroidApiLevel.B)
        .compile()
        .inspect(this::assertSingleWrappers)
        .addDesugaredCoreLibraryRunClassPath(
            this::buildDesugaredLibraryWithConversionExtension, AndroidApiLevel.B)
        .addRunClasspathFiles(customLib)
        .run(new DexRuntime(DexVm.ART_9_0_0_HOST), Executor.class)
        .assertSuccessWithOutput(
            StringUtils.lines("Object1 Object2 Object3", "2", "false", "3", "true", "5", "42.0"));
  }

  private void assertSingleWrappers(CodeInspector i) {
    List<FoundClassSubject> intSupplierWrapperClasses =
        i.allClasses().stream()
            .filter(c -> c.getOriginalName().contains("IntSupplier"))
            .collect(Collectors.toList());
    assertEquals(
        "Expected 1 IntSupplier wrapper but got " + intSupplierWrapperClasses,
        1,
        intSupplierWrapperClasses.size());

    List<FoundClassSubject> doubleSupplierWrapperClasses =
        i.allClasses().stream()
            .filter(c -> c.getOriginalName().contains("DoubleSupplier"))
            .collect(Collectors.toList());
    assertEquals(
        "Expected 1 DoubleSupplier wrapper but got " + doubleSupplierWrapperClasses,
        1,
        doubleSupplierWrapperClasses.size());
  }

  static class Executor {

    public static void main(String[] args) {
      Function<Object1, Object3> function = CustomLibClass.mixFunction(Object2::new, Object3::new);
      System.out.println(function.apply(new Object1()).toString());
      BiFunction<String, String, Character> biFunction =
          CustomLibClass.mixBiFunctions((String i, String j) -> i + j, (String s) -> s.charAt(1));
      System.out.println(biFunction.apply("1", "2"));
      BooleanSupplier booleanSupplier = CustomLibClass.mixBoolSuppliers(() -> true, () -> false);
      System.out.println(booleanSupplier.getAsBoolean());
      LongConsumer longConsumer = CustomLibClass.mixLong(() -> 1L, System.out::println);
      longConsumer.accept(2L);
      DoublePredicate doublePredicate =
          CustomLibClass.mixPredicate(d -> d > 1.0, d -> d == 2.0, d -> d < 3.0);
      System.out.println(doublePredicate.test(2.0));
      // Reverse wrapper should not exist.
      System.out.println(CustomLibClass.extractInt(() -> 5));
      System.out.println(CustomLibClass.getDoubleSupplier().getAsDouble());
    }

    static class Object1 {}

    static class Object2 {

      private Object1 field;

      private Object2(Object1 o) {
        this.field = o;
      }
    }

    static class Object3 {
      private Object2 field;

      private Object3(Object2 o) {
        this.field = o;
      }

      @Override
      public String toString() {
        return field.field.getClass().getSimpleName()
            + " "
            + field.getClass().getSimpleName()
            + " "
            + getClass().getSimpleName();
      }
    }
  }

  // This class will be put at compilation time as library and on the runtime class path.
  // This class is convenient for easy testing. Each method plays the role of methods in the
  // platform APIs for which argument/return values need conversion.
  static class CustomLibClass {

    public static <T, Q, R> Function<T, R> mixFunction(Function<T, Q> f1, Function<Q, R> f2) {
      return f1.andThen(f2);
    }

    public static <T, R> BiFunction<T, T, R> mixBiFunctions(
        BinaryOperator<T> operator, Function<T, R> function) {
      return operator.andThen(function);
    }

    public static BooleanSupplier mixBoolSuppliers(
        BooleanSupplier supplier1, BooleanSupplier supplier2) {
      return () -> supplier1.getAsBoolean() && supplier2.getAsBoolean();
    }

    public static LongConsumer mixLong(LongSupplier supplier, LongConsumer consumer) {
      return l -> consumer.accept(l + supplier.getAsLong());
    }

    public static DoublePredicate mixPredicate(
        DoublePredicate predicate1, DoublePredicate predicate2, DoublePredicate predicate3) {
      return predicate1.and(predicate2).and(predicate3);
    }

    public static int extractInt(IntSupplier supplier) {
      return supplier.getAsInt();
    }

    public static DoubleSupplier getDoubleSupplier() {
      return () -> 42.0;
    }
  }
}
