// 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 com.android.tools.r8.DiagnosticsMatcher.diagnosticOrigin;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.StringResource;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestDiagnosticMessages;
import com.android.tools.r8.TestDiagnosticMessagesImpl;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime.NoneRuntime;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfigurationParser;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AbortException;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.SemanticVersion;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class DesugaredLibraryConfigurationParsingTest extends TestBase {

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withNoneRuntime().build();
  }

  public DesugaredLibraryConfigurationParsingTest(TestParameters parameters) {
    assertEquals(NoneRuntime.getInstance(), parameters.getRuntime());
  }

  final AndroidApiLevel minApi = AndroidApiLevel.B;
  final boolean libraryCompilation = true;

  final DexItemFactory factory = new DexItemFactory();
  final Origin origin =
      new Origin(Origin.root()) {
        @Override
        public String part() {
          return "Test Origin";
        }
      };

  final Map<String, Object> TEMPLATE =
      ImmutableMap.<String, Object>builder()
          .put(
              "configuration_format_version",
              DesugaredLibraryConfigurationParser.MAX_SUPPORTED_VERSION)
          .put("group_id", "com.tools.android")
          .put("artifact_id", "desugar_jdk_libs")
          .put("version", DesugaredLibraryConfigurationParser.MIN_SUPPORTED_VERSION.toString())
          .put("required_compilation_api_level", 1)
          .put("synthesized_library_classes_package_prefix", "j$.")
          .put("common_flags", Collections.emptyList())
          .put("program_flags", Collections.emptyList())
          .put("library_flags", Collections.emptyList())
          .build();

  private LinkedHashMap<String, Object> template() {
    return new LinkedHashMap<>(TEMPLATE);
  }

  private DesugaredLibraryConfigurationParser parser(DiagnosticsHandler handler) {
    return new DesugaredLibraryConfigurationParser(
        factory, new Reporter(handler), libraryCompilation, minApi.getLevel());
  }

  private DesugaredLibraryConfiguration runPassing(String resource) {
    return runPassing(StringResource.fromString(resource, origin));
  }

  private DesugaredLibraryConfiguration runPassing(StringResource resource) {
    TestDiagnosticMessagesImpl handler = new TestDiagnosticMessagesImpl();
    DesugaredLibraryConfiguration config = parser(handler).parse(resource);
    handler.assertNoMessages();
    return config;
  }

  private void runFailing(String json, Consumer<TestDiagnosticMessages> checker) {
    TestDiagnosticMessagesImpl handler = new TestDiagnosticMessagesImpl();
    try {
      parser(handler).parse(StringResource.fromString(json, origin));
      fail("Expected failure");
    } catch (AbortException e) {
      checker.accept(handler);
    }
  }

  @Test
  public void testReference() throws Exception {
    // Just test that the reference file parses without issues.
    DesugaredLibraryConfiguration config =
        runPassing(StringResource.fromFile(ToolHelper.DESUGAR_LIB_JSON_FOR_TESTING));
    assertEquals(libraryCompilation, config.isLibraryCompilation());
  }

  @Test
  public void testEmpty() {
    runFailing(
        "",
        diagnostics -> {
          diagnostics.assertErrorsMatch(
              allOf(
                  diagnosticMessage(containsString("Not a JSON Object")),
                  diagnosticOrigin(origin)));
        });
  }

  @Test
  public void testRequiredKeys() {
    ImmutableList<String> requiredKeys =
        ImmutableList.of(
            "configuration_format_version",
            "group_id",
            "artifact_id",
            "version",
            "required_compilation_api_level",
            "synthesized_library_classes_package_prefix",
            "common_flags",
            "program_flags",
            "library_flags");
    for (String key : requiredKeys) {
      Map<String, Object> data = template();
      data.remove(key);
      runFailing(
          toJson(data),
          diagnostics ->
              diagnostics.assertErrorsMatch(
                  allOf(
                      diagnosticMessage(containsString("Invalid desugared library configuration")),
                      diagnosticMessage(containsString("Expected required key '" + key + "'")),
                      diagnosticOrigin(origin))));
    }
  }

  @Test
  public void testUnsupportedVersion() {
    LinkedHashMap<String, Object> data = template();
    SemanticVersion minVersion = DesugaredLibraryConfigurationParser.MIN_SUPPORTED_VERSION;
    data.put(
        "version",
        new SemanticVersion(minVersion.getMajor(), minVersion.getMinor(), minVersion.getPatch() - 1)
            .toString());
    runFailing(
        toJson(data),
        diagnostics ->
            diagnostics.assertErrorsMatch(
                allOf(
                    diagnosticMessage(containsString("upgrade the desugared library")),
                    diagnosticOrigin(origin))));
  }

  @Test
  public void testUnsupportedAbove() {
    LinkedHashMap<String, Object> data = template();
    data.put("configuration_format_version", 100000);
    runFailing(
        toJson(data),
        diagnostics ->
            diagnostics.assertErrorsMatch(
                allOf(
                    diagnosticMessage(containsString("upgrade the D8/R8 compiler")),
                    diagnosticOrigin(origin))));
  }

  @Test
  public void testCustomAndWrapperOverlap() {
    LinkedHashMap<String, Object> data = template();
    data.put(
        "common_flags",
        ImmutableList.of(
            ImmutableMap.of(
                "api_level_below_or_equal",
                100000,
                "custom_conversion",
                ImmutableMap.of("java.util.Foo", "j$.util.FooConv"),
                "wrapper_conversion",
                ImmutableList.of("java.util.Foo"))));
    runFailing(
        toJson(data),
        diagnostics ->
            diagnostics.assertErrorsMatch(
                allOf(
                    diagnosticMessage(containsString("Duplicate types")),
                    diagnosticMessage(containsString("java.util.Foo")),
                    diagnosticOrigin(origin))));
  }

  @Test
  public void testRedefinition() {
    LinkedHashMap<String, Object> data = template();
    data.put(
        "common_flags",
        ImmutableList.of(
            ImmutableMap.of(
                "api_level_below_or_equal",
                100000,
                "custom_conversion",
                ImmutableMap.of("java.util.Foo", "j$.util.FooConv1"))));
    data.put(
        "library_flags",
        ImmutableList.of(
            ImmutableMap.of(
                "api_level_below_or_equal",
                100000,
                "custom_conversion",
                ImmutableMap.of("java.util.Foo", "j$.util.FooConv2"))));
    runFailing(
        toJson(data),
        diagnostics ->
            diagnostics.assertErrorsMatch(
                allOf(
                    diagnosticMessage(containsString("Duplicate assignment of key")),
                    diagnosticMessage(containsString("java.util.Foo")),
                    diagnosticMessage(containsString("custom_conversion")),
                    diagnosticOrigin(origin))));
  }

  @Test
  public void testDuplicate() {
    LinkedHashMap<String, Object> data = template();
    data.put(
        "common_flags",
        ImmutableList.of(
            ImmutableMap.of(
                "api_level_below_or_equal",
                100000,
                "custom_conversion",
                ImmutableMap.of(
                    "java.util.Foo", "j$.util.FooConv1",
                    "java.util.Foo2", "j$.util.FooConv2"))));
    // The gson parser will overwrite the key in order during parsing, thus hiding potential issues.
    DesugaredLibraryConfiguration config = runPassing(toJson(data).replace("Foo2", "Foo"));
    assertEquals(
        Collections.singletonList("java.util.Foo"),
        config.getCustomConversions().keySet().stream()
            .map(DexType::toString)
            .collect(Collectors.toList()));
    assertEquals(
        Collections.singletonList("j$.util.FooConv2"),
        config.getCustomConversions().values().stream()
            .map(DexType::toString)
            .collect(Collectors.toList()));
  }

  // JSON building helpers.
  // This does not use gson to make the text input construction independent of gson.

  private static String toJson(Map<String, Object> data) {
    StringBuilder builder = new StringBuilder();
    toJsonObject(data, builder);
    return builder.toString();
  }

  private static void toJsonObject(Map<String, Object> data, StringBuilder builder) {
    StringUtils.append(
        builder,
        ListUtils.map(
            data.entrySet(),
            entry -> "\n  " + quote(entry.getKey()) + ": " + toJsonElement(entry.getValue())),
        ", ",
        BraceType.TUBORG);
  }

  private static String toJsonElement(Object element) {
    StringBuilder builder = new StringBuilder();
    toJsonElement(element, builder);
    return builder.toString();
  }

  private static void toJsonElement(Object element, StringBuilder builder) {
    if (element instanceof String) {
      builder.append(quote((String) element));
    } else if (element instanceof Integer) {
      builder.append(element);
    } else if (element instanceof List) {
      toJsonList((List<Object>) element, builder);
    } else if (element instanceof Map) {
      toJsonObject((Map<String, Object>) element, builder);
    } else {
      throw new IllegalStateException("Unexpected object type: " + element.getClass());
    }
  }

  private static void toJsonList(List<Object> element, StringBuilder builder) {
    StringUtils.append(
        builder, ListUtils.map(element, o -> "\n  " + toJsonElement(o)), ", ", BraceType.SQUARE);
  }

  private static String quote(String str) {
    return "\"" + str + "\"";
  }
}
