// 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.ir.desugar.desugaredlibrary.specificationconversion;

import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanRewritingFlags;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineRewritingFlags;
import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;

public class HumanToMachinePrefixConverter {

  private final AppInfoWithClassHierarchy appInfo;
  private final MachineRewritingFlags.Builder builder;
  private final String synthesizedPrefix;
  private final boolean libraryCompilation;
  private final Map<DexString, DexString> descriptorPrefix;
  private final Set<DexString> descriptorMaintainPrefix;
  private final Set<DexString> descriptorDontRewritePrefix;
  private final Map<DexString, Map<DexString, DexString>> descriptorDifferentPrefix;
  private final Set<DexString> usedPrefix = Sets.newIdentityHashSet();
  private final boolean jdk11Legacy;

  public HumanToMachinePrefixConverter(
      AppInfoWithClassHierarchy appInfo,
      MachineRewritingFlags.Builder builder,
      String synthesizedPrefix,
      boolean libraryCompilation,
      String identifier,
      HumanRewritingFlags rewritingFlags) {
    this.appInfo = appInfo;
    this.builder = builder;
    this.synthesizedPrefix = synthesizedPrefix;
    this.libraryCompilation = libraryCompilation;
    this.descriptorPrefix = convertRewritePrefix(rewritingFlags.getRewritePrefix());
    this.descriptorDontRewritePrefix = convertPrefixSet(rewritingFlags.getDontRewritePrefix());
    this.descriptorMaintainPrefix = convertPrefixSet(rewritingFlags.getMaintainPrefix());
    this.descriptorDifferentPrefix =
        convertRewriteDifferentPrefix(rewritingFlags.getRewriteDerivedPrefix());
    this.jdk11Legacy = identifier.startsWith("com.tools.android:desugar_jdk_libs:1.2.");
  }

  public void convertPrefixFlags(
      HumanRewritingFlags rewritingFlags, BiConsumer<String, Set<DexString>> warnConsumer) {
    rewriteClasses();
    rewriteValues(rewritingFlags.getRetargetMethodToType());
    rewriteValues(rewritingFlags.getRetargetMethodEmulatedDispatchToType());
    rewriteValues(rewritingFlags.getCustomConversions());
    rewriteMethodValues(rewritingFlags.getRetargetMethodToMethod());
    rewriteMethodValues(rewritingFlags.getRetargetMethodEmulatedDispatchToMethod());
    rewriteEmulatedInterface(rewritingFlags.getEmulatedInterfaces());
    rewriteRetargetKeys(rewritingFlags.getRetargetMethodEmulatedDispatchToType());
    rewriteRetargetKeys(rewritingFlags.getRetargetMethodEmulatedDispatchToMethod());
    rewriteApiConversions(rewritingFlags.getApiGenericConversion());
    warnIfUnusedPrefix(warnConsumer);
  }

  private void warnIfUnusedPrefix(BiConsumer<String, Set<DexString>> warnConsumer) {
    Set<DexString> unused = Sets.newIdentityHashSet();
    unused.addAll(descriptorPrefix.keySet());
    unused.addAll(descriptorMaintainPrefix);
    unused.addAll(descriptorDifferentPrefix.keySet());
    unused.removeAll(usedPrefix);
    if (jdk11Legacy) {
      // We have to allow duplicate because of the jdk11 legacy configuration, since there is no
      // api_greater_or_equal in legacy, we're bound to have duplicates.
      // If we have x.y. -> w.z and x. -> w., then if one is used the other is used.
      List<DexString> duplicates = new ArrayList<>();
      for (DexString prefix : unused) {
        descriptorPrefix.forEach(
            (k, v) -> {
              if (!unused.contains(k) && (k.startsWith(prefix) || prefix.startsWith(k))) {
                duplicates.add(prefix);
              }
            });
      }
      duplicates.forEach(unused::remove);
    }
    warnConsumer.accept("The following prefixes do not match any type: ", unused);
  }

  public DexType convertJavaNameToDesugaredLibrary(DexType type) {
    String convertedPrefix = DescriptorUtils.getJavaTypeFromBinaryName(synthesizedPrefix);
    String interfaceType = type.toString();
    int firstPackage = interfaceType.indexOf('.');
    return appInfo
        .dexItemFactory()
        .createType(
            DescriptorUtils.javaTypeToDescriptor(
                convertedPrefix + interfaceType.substring(firstPackage + 1)));
  }

  private void rewriteRetargetKeys(Map<DexMethod, ?> retarget) {
    for (DexMethod dexMethod : retarget.keySet()) {
      DexType type = convertJavaNameToDesugaredLibrary(dexMethod.holder);
      builder.rewriteDerivedTypeOnly(dexMethod.holder, type);
    }
  }

  private void rewriteApiConversions(Map<DexMethod, DexMethod[]> apiGenericConversions) {
    apiGenericConversions.forEach(
        (k, v) -> {
          for (DexMethod dexMethod : v) {
            if (dexMethod != null) {
              registerType(dexMethod.getHolderType());
            }
          }
        });
  }

  private void rewriteEmulatedInterface(Map<DexType, DexType> emulateLibraryInterface) {
    emulateLibraryInterface.forEach(builder::rewriteDerivedTypeOnly);
  }

  private void rewriteValues(
      Map<?, DexType> flags) {
    for (DexType type : flags.values()) {
      registerType(type);
    }
  }

  private void rewriteMethodValues(Map<?, DexMethod> flags) {
    for (DexMethod method : flags.values()) {
      registerType(method.getHolderType());
    }
  }

  private void rewriteClasses() {
    appInfo.app().forEachLibraryType(this::registerClassType);
    if (libraryCompilation) {
      appInfo.app().forEachProgramType(this::registerClassType);
    }
  }

  private void registerClassType(DexType type) {
    registerType(type);
    registerMaintainType(type);
    registerDifferentType(type);
  }

  private void registerType(DexType type) {
    DexType rewrittenType = rewrittenType(type);
    if (rewrittenType != null) {
      if (prefixMatching(type, descriptorDontRewritePrefix) != null) {
        return;
      }
      builder.rewriteType(type, rewrittenType);
    }
  }

  private void registerMaintainType(DexType type) {
    DexString prefix = prefixMatching(type, descriptorMaintainPrefix);
    if (prefix == null) {
      return;
    }
    builder.maintainType(type);
    // We cannot rely on the synthetic classes being on the same package anyway since the runtime
    // may use a class from the Android framework which is considered in a different package even
    // if the package name is identical.
    // This is required since the Android framework also generates external synthetics for lambdas
    // that are publicly visible.
    builder.rewriteDerivedTypeOnly(type, convertJavaNameToDesugaredLibrary(type));
    usedPrefix.add(prefix);
  }

  private void registerDifferentType(DexType type) {
    DexString prefix = prefixMatching(type, descriptorDifferentPrefix.keySet());
    if (prefix == null) {
      return;
    }
    descriptorDifferentPrefix
        .get(prefix)
        .forEach(
            (k, v) -> {
              DexString typeDescriptor =
                  type.descriptor.withNewPrefix(prefix, k, appInfo.dexItemFactory());
              DexString rewrittenTypeDescriptor =
                  type.descriptor.withNewPrefix(prefix, v, appInfo.dexItemFactory());
              DexType newKey = appInfo.dexItemFactory().createType(typeDescriptor);
              assert appInfo.definitionForWithoutExistenceAssert(newKey) == null
                  : "Trying to rewrite a type "
                      + newKey
                      + " with different prefix that already exists.";
              builder.rewriteType(
                  newKey, appInfo.dexItemFactory().createType(rewrittenTypeDescriptor));
            });
    usedPrefix.add(prefix);
  }

  private DexString prefixMatching(DexType type, Set<DexString> prefixes) {
    DexString prefixToMatch = type.descriptor.withoutArray(appInfo.dexItemFactory());
    for (DexString prefix : prefixes) {
      if (prefixToMatch.startsWith(prefix)) {
        return prefix;
      }
    }
    return null;
  }

  private DexType rewrittenType(DexType type) {
    DexString prefix = prefixMatching(type, descriptorPrefix.keySet());
    if (prefix == null) {
      return null;
    }
    DexString rewrittenTypeDescriptor =
        type.descriptor.withNewPrefix(
            prefix, descriptorPrefix.get(prefix), appInfo.dexItemFactory());
    usedPrefix.add(prefix);
    return appInfo.dexItemFactory().createType(rewrittenTypeDescriptor);
  }

  private ImmutableMap<DexString, Map<DexString, DexString>> convertRewriteDifferentPrefix(
      Map<String, Map<String, String>> rewriteDerivedPrefix) {
    ImmutableMap.Builder<DexString, Map<DexString, DexString>> mapBuilder = ImmutableMap.builder();
    for (String key : rewriteDerivedPrefix.keySet()) {
      mapBuilder.put(toDescriptorPrefix(key), convertRewritePrefix(rewriteDerivedPrefix.get(key)));
    }
    return mapBuilder.build();
  }

  private ImmutableSet<DexString> convertPrefixSet(Set<String> maintainPrefix) {
    ImmutableSet.Builder<DexString> builder = ImmutableSet.builder();
    for (String prefix : maintainPrefix) {
      builder.add(toDescriptorPrefix(prefix));
    }
    return builder.build();
  }

  private ImmutableMap<DexString, DexString> convertRewritePrefix(
      Map<String, String> rewritePrefix) {
    ImmutableMap.Builder<DexString, DexString> mapBuilder = ImmutableMap.builder();
    for (String key : rewritePrefix.keySet()) {
      mapBuilder.put(toDescriptorPrefix(key), toDescriptorPrefix(rewritePrefix.get(key)));
    }
    return mapBuilder.build();
  }

  private DexString toDescriptorPrefix(String prefix) {
    return appInfo
        .dexItemFactory()
        .createString("L" + DescriptorUtils.getBinaryNameFromJavaType(prefix));
  }
}
