// 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.conversiontests;

import com.android.tools.r8.TestParameters;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.desugar.desugaredlibrary.conversiontests.MoreFunctionConversionTest.CustomLibClass;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.DoubleSummaryStatistics;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.LongSummaryStatistics;
import org.junit.BeforeClass;
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 SummaryStatisticsConversionTest extends DesugaredLibraryTestBase {

  private final TestParameters parameters;
  private final boolean shrinkDesugaredLibrary;
  private static final AndroidApiLevel MIN_SUPPORTED = AndroidApiLevel.N;
  private static final String EXPECTED_RESULT =
      StringUtils.lines(
          "2", "1", "42", "42", "42", "1", "42", "42", "42", "1", "42.0", "42.0", "42.0");
  private static Path CUSTOM_LIB;

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

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

  @BeforeClass
  public static void compileCustomLib() throws Exception {
    CUSTOM_LIB =
        testForD8(getStaticTemp())
            .addProgramClasses(CustomLibClass.class)
            .setMinApi(MIN_SUPPORTED)
            .compile()
            .writeToZip();
  }

  @Test
  public void testStatsD8() throws Exception {
    KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
    testForD8()
        .setMinApi(parameters.getApiLevel())
        .addProgramClasses(Executor.class)
        .addLibraryClasses(CustomLibClass.class)
        .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
        .compile()
        .addDesugaredCoreLibraryRunClassPath(
            this::buildDesugaredLibrary,
            parameters.getApiLevel(),
            keepRuleConsumer.get(),
            shrinkDesugaredLibrary)
        .addRunClasspathFiles(CUSTOM_LIB)
        .run(parameters.getRuntime(), Executor.class)
        .assertSuccessWithOutput(EXPECTED_RESULT);
  }

  @Test
  public void testStatsR8() throws Exception {
    KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
    testForR8(parameters.getBackend())
        .setMinApi(parameters.getApiLevel())
        .addProgramClasses(Executor.class)
        .addKeepMainRule(Executor.class)
        .addLibraryClasses(CustomLibClass.class)
        .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
        .compile()
        .addDesugaredCoreLibraryRunClassPath(
            this::buildDesugaredLibrary,
            parameters.getApiLevel(),
            keepRuleConsumer.get(),
            shrinkDesugaredLibrary)
        .addRunClasspathFiles(CUSTOM_LIB)
        .run(parameters.getRuntime(), Executor.class)
        .assertSuccessWithOutput(EXPECTED_RESULT);
  }

  static class Executor {

    public static void main(String[] args) {
      // The realTest represents scenario applicable in Android apps, subsequent tests use
      // mocked CustomLib to ensure all cases are correct.
      realTest();
      longTest();
      intTest();
      doubleTest();
    }

    private static void realTest() {
      System.out.println("foo".subSequence(0, 2).codePoints().summaryStatistics().getCount());
    }

    public static void longTest() {
      long[] longs = new long[1];
      longs[0] = 42L;
      LongSummaryStatistics mix =
          CustomLibClass.mix(Arrays.stream(longs).summaryStatistics(), new LongSummaryStatistics());
      System.out.println(mix.getCount());
      System.out.println(mix.getMin());
      System.out.println(mix.getMax());
      System.out.println(mix.getSum());
    }

    public static void intTest() {
      int[] ints = new int[1];
      ints[0] = 42;
      IntSummaryStatistics mix =
          CustomLibClass.mix(Arrays.stream(ints).summaryStatistics(), new IntSummaryStatistics());
      System.out.println(mix.getCount());
      System.out.println(mix.getMin());
      System.out.println(mix.getMax());
      System.out.println(mix.getSum());
    }

    public static void doubleTest() {
      double[] doubles = new double[1];
      doubles[0] = 42L;
      DoubleSummaryStatistics mix =
          CustomLibClass.mix(
              Arrays.stream(doubles).summaryStatistics(), new DoubleSummaryStatistics());
      System.out.println(mix.getCount());
      System.out.println(mix.getMin());
      System.out.println(mix.getMax());
      System.out.println(mix.getSum());
    }
  }

  // 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 LongSummaryStatistics mix(
        LongSummaryStatistics stats1, LongSummaryStatistics stats2) {
      return stats1;
    }

    public static IntSummaryStatistics mix(
        IntSummaryStatistics stats1, IntSummaryStatistics stats2) {
      return stats1;
    }

    public static DoubleSummaryStatistics mix(
        DoubleSummaryStatistics stats1, DoubleSummaryStatistics stats2) {
      return stats1;
    }
  }
}
