// Copyright (c) 2021, 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.ir.desugar.desugaredlibrary.humanspecification;

import static com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecificationParser.CONFIGURATION_FORMAT_VERSION_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.AMEND_LIBRARY_METHOD_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.API_LEVEL_BELOW_OR_EQUAL_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.BACKPORT_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.COMMON_FLAGS_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.CURRENT_HUMAN_CONFIGURATION_FORMAT_VERSION;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.CUSTOM_CONVERSION_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.DONT_RETARGET_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.DONT_REWRITE_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.EMULATE_INTERFACE_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.IDENTIFIER_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.LIBRARY_FLAGS_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.PROGRAM_FLAGS_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.REQUIRED_COMPILATION_API_LEVEL_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.RETARGET_METHOD_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.REWRITE_DERIVED_PREFIX_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.REWRITE_PREFIX_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.SHRINKER_CONFIG_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.SUPPORT_ALL_CALLBACKS_FROM_LIBRARY_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.SYNTHESIZED_LIBRARY_CLASSES_PACKAGE_PREFIX_KEY;
import static com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanDesugaredLibrarySpecificationParser.WRAPPER_CONVERSION_KEY;

import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class MultiAPILevelHumanDesugaredLibrarySpecificationJsonExporter {

  public static void export(
      MultiAPILevelHumanDesugaredLibrarySpecification specification, StringConsumer output) {
    new MultiAPILevelHumanDesugaredLibrarySpecificationJsonExporter()
        .internalExport(specification, output);
  }

  private void internalExport(
      MultiAPILevelHumanDesugaredLibrarySpecification humanSpec, StringConsumer output) {
    HashMap<String, Object> toJson = new LinkedHashMap<>();
    toJson.put(IDENTIFIER_KEY, humanSpec.getTopLevelFlags().getIdentifier());
    toJson.put(CONFIGURATION_FORMAT_VERSION_KEY, CURRENT_HUMAN_CONFIGURATION_FORMAT_VERSION);
    toJson.put(
        REQUIRED_COMPILATION_API_LEVEL_KEY,
        humanSpec.getTopLevelFlags().getRequiredCompilationAPILevel().getLevel());
    toJson.put(
        SYNTHESIZED_LIBRARY_CLASSES_PACKAGE_PREFIX_KEY,
        humanSpec.getTopLevelFlags().getSynthesizedLibraryClassesPackagePrefix().replace('/', '.'));
    toJson.put(
        SUPPORT_ALL_CALLBACKS_FROM_LIBRARY_KEY,
        humanSpec.getTopLevelFlags().supportAllCallbacksFromLibrary());

    toJson.put(COMMON_FLAGS_KEY, rewritingFlagsToString(humanSpec.getCommonFlags()));
    toJson.put(PROGRAM_FLAGS_KEY, rewritingFlagsToString(humanSpec.getProgramFlags()));
    toJson.put(LIBRARY_FLAGS_KEY, rewritingFlagsToString(humanSpec.getLibraryFlags()));

    toJson.put(SHRINKER_CONFIG_KEY, humanSpec.getTopLevelFlags().getExtraKeepRules());

    Gson gson = new Gson();
    String export = gson.toJson(toJson);
    output.accept(export, new DiagnosticsHandler() {});
  }

  private List<Object> rewritingFlagsToString(
      Int2ObjectMap<HumanRewritingFlags> rewritingFlagsMap) {
    ArrayList<Object> list = new ArrayList<>();
    ArrayList<Integer> apis = new ArrayList<>(rewritingFlagsMap.keySet());
    apis.sort(Comparator.reverseOrder());
    for (int apiBelowOrEqual : apis) {
      HumanRewritingFlags flags = rewritingFlagsMap.get(apiBelowOrEqual);
      HashMap<String, Object> toJson = new LinkedHashMap<>();
      toJson.put(API_LEVEL_BELOW_OR_EQUAL_KEY, apiBelowOrEqual);
      if (!flags.getRewritePrefix().isEmpty()) {
        toJson.put(REWRITE_PREFIX_KEY, new TreeMap<>(flags.getRewritePrefix()));
      }
      if (!flags.getRewriteDerivedPrefix().isEmpty()) {
        TreeMap<String, Map<String, String>> rewriteDerivedPrefix = new TreeMap<>();
        flags
            .getRewriteDerivedPrefix()
            .forEach((k, v) -> rewriteDerivedPrefix.put(k, new TreeMap<>(v)));
        toJson.put(REWRITE_DERIVED_PREFIX_KEY, rewriteDerivedPrefix);
      }
      if (!flags.getEmulatedInterfaces().isEmpty()) {
        toJson.put(EMULATE_INTERFACE_KEY, mapToString(flags.getEmulatedInterfaces()));
      }
      if (!flags.getDontRewriteInvocation().isEmpty()) {
        toJson.put(DONT_REWRITE_KEY, setToString(flags.getDontRewriteInvocation()));
      }
      if (!flags.getRetargetMethod().isEmpty()) {
        toJson.put(RETARGET_METHOD_KEY, mapToString(flags.getRetargetMethod()));
      }
      if (!flags.getDontRetarget().isEmpty()) {
        toJson.put(DONT_RETARGET_KEY, setToString(flags.getDontRetarget()));
      }
      if (!flags.getLegacyBackport().isEmpty()) {
        toJson.put(BACKPORT_KEY, mapToString(flags.getLegacyBackport()));
      }
      if (!flags.getWrapperConversions().isEmpty()) {
        toJson.put(WRAPPER_CONVERSION_KEY, setToString(flags.getWrapperConversions()));
      }
      if (!flags.getCustomConversions().isEmpty()) {
        toJson.put(CUSTOM_CONVERSION_KEY, mapToString(flags.getCustomConversions()));
      }
      if (!flags.getAmendLibraryMethod().isEmpty()) {
        toJson.put(AMEND_LIBRARY_METHOD_KEY, amendLibraryToString(flags.getAmendLibraryMethod()));
      }
      list.add(toJson);
    }
    return list;
  }

  private Set<String> amendLibraryToString(Map<DexMethod, MethodAccessFlags> amendLibraryMembers) {
    Set<String> stringSet = Sets.newHashSet();
    amendLibraryMembers.forEach(
        (member, flags) -> stringSet.add(flags.toString() + " " + toString(member)));
    return stringSet;
  }

  private Set<String> setToString(Set<? extends DexItem> set) {
    Set<String> stringSet = Sets.newHashSet();
    set.forEach(e -> stringSet.add(toString(e)));
    return stringSet;
  }

  private Map<String, String> mapToString(Map<? extends DexItem, ? extends DexItem> map) {
    Map<String, String> stringMap = new TreeMap<>();
    map.forEach((k, v) -> stringMap.put(toString(k), toString(v)));
    return stringMap;
  }

  private String toString(DexItem o) {
    if (o instanceof DexType) {
      return o.toString();
    }
    if (o instanceof DexMethod) {
      DexMethod method = (DexMethod) o;
      StringBuilder sb =
          new StringBuilder()
              .append(method.getReturnType())
              .append(" ")
              .append(method.getHolderType())
              .append("#")
              .append(method.getName())
              .append("(");
      for (int i = 0; i < method.getParameters().size(); i++) {
        sb.append(method.getParameter(i));
        if (i != method.getParameters().size() - 1) {
          sb.append(", ");
        }
      }
      sb.append(")");
      return sb.toString();
    }
    throw new Unreachable();
  }
}
