// Copyright (c) 2022, 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.TestDiagnosticMessages;
import com.android.tools.r8.TestDiagnosticMessagesImpl;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
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.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecificationParser;
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.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class LegacyDesugaredLibraryConfigurationParsingTest extends DesugaredLibraryTestBase {

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

  public LegacyDesugaredLibraryConfigurationParsingTest(TestParameters parameters) {
    parameters.assertNoneRuntime();
  }

  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",
              LegacyDesugaredLibrarySpecificationParser.MAX_SUPPORTED_VERSION)
          .put("group_id", "com.tools.android")
          .put("artifact_id", "desugar_jdk_libs")
          .put(
              "version", LegacyDesugaredLibrarySpecificationParser.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 LegacyDesugaredLibrarySpecificationParser parser(DiagnosticsHandler handler) {
    Assume.assumeFalse(isJDK11DesugaredLibrary());
    return new LegacyDesugaredLibrarySpecificationParser(
        factory, new Reporter(handler), libraryCompilation, minApi.getLevel());
  }

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

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

  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.
    LegacyDesugaredLibrarySpecification spec =
        runPassing(StringResource.fromFile(ToolHelper.getDesugarLibJsonForTesting()));
    assertEquals(libraryCompilation, spec.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 = LegacyDesugaredLibrarySpecificationParser.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", 99);
    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.
    LegacyDesugaredLibrarySpecification spec = runPassing(toJson(data).replace("Foo2", "Foo"));
    assertEquals(
        Collections.singletonList("java.util.Foo"),
        spec.getCustomConversions().keySet().stream()
            .map(DexType::toString)
            .collect(Collectors.toList()));
    assertEquals(
        Collections.singletonList("j$.util.FooConv2"),
        spec.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) {
      @SuppressWarnings("unchecked")
      List<Object> elements = (List<Object>) element;
      toJsonList(elements, builder);
    } else if (element instanceof Map) {
      @SuppressWarnings("unchecked")
      Map<String, Object> elements = (Map<String, Object>) element;
      toJsonObject(elements, 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 + "\"";
  }
}
