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

import com.android.tools.r8.Version;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringForTesting;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.structural.Equatable;
import com.android.tools.r8.utils.structural.Ordered;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class SyntheticNaming {

  private KindGenerator generator = new KindGenerator();

  // Global synthetics.
  public final SyntheticKind RECORD_TAG = generator.forGlobalClass();
  public final SyntheticKind API_MODEL_STUB = generator.forGlobalClass();
  public final SyntheticKind METHOD_HANDLES_LOOKUP = generator.forGlobalClass();
  public final SyntheticKind VAR_HANDLE = generator.forGlobalClass();

  // Classpath only synthetics in the global type namespace.
  public final SyntheticKind GENERIC_API_CONVERSION_STUB = generator.forGlobalClasspathClass();
  public final SyntheticKind RETARGET_STUB = generator.forGlobalClasspathClass();
  public final SyntheticKind EMULATED_INTERFACE_MARKER_CLASS = generator.forGlobalClasspathClass();

  // Fixed suffix synthetics. Each has a hygienic prefix type.
  public final SyntheticKind ENUM_UNBOXING_LOCAL_UTILITY_CLASS =
      generator.forFixedClass("$EnumUnboxingLocalUtility");
  public final SyntheticKind ENUM_UNBOXING_SHARED_UTILITY_CLASS =
      generator.forFixedClass("$EnumUnboxingSharedUtility");
  public final SyntheticKind COMPANION_CLASS = generator.forFixedClass(COMPANION_CLASS_SUFFIX);
  public final SyntheticKind EMULATED_INTERFACE_CLASS =
      generator.forFixedClass(InterfaceDesugaringForTesting.EMULATED_INTERFACE_CLASS_SUFFIX);
  public final SyntheticKind RETARGET_CLASS = generator.forFixedClass("RetargetClass");
  public final SyntheticKind RETARGET_INTERFACE = generator.forFixedClass("RetargetInterface");
  public final SyntheticKind WRAPPER = generator.forFixedClass("$Wrapper");
  public final SyntheticKind VIVIFIED = generator.forFixedClass("");
  public final SyntheticKind VIVIFIED_WRAPPER = generator.forFixedClass("$VivifiedWrapper");
  public final SyntheticKind INIT_TYPE_ARGUMENT = generator.forFixedClass("-IA");
  public final SyntheticKind HORIZONTAL_INIT_TYPE_ARGUMENT_1 =
      generator.forFixedClass(SYNTHETIC_CLASS_SEPARATOR + "IA$1");
  public final SyntheticKind HORIZONTAL_INIT_TYPE_ARGUMENT_2 =
      generator.forFixedClass(SYNTHETIC_CLASS_SEPARATOR + "IA$2");
  public final SyntheticKind HORIZONTAL_INIT_TYPE_ARGUMENT_3 =
      generator.forFixedClass(SYNTHETIC_CLASS_SEPARATOR + "IA$3");
  public final SyntheticKind ENUM_CONVERSION = generator.forFixedClass("$EnumConversion");

  // Locally generated synthetic classes.
  public final SyntheticKind LAMBDA = generator.forInstanceClass("Lambda");
  public final SyntheticKind THREAD_LOCAL = generator.forInstanceClass("ThreadLocal");

  // TODO(b/214901256): Sharing of synthetic classes may lead to duplicate method errors.
  public final SyntheticKind NON_FIXED_INIT_TYPE_ARGUMENT =
      generator.forNonSharableInstanceClass("$IA");
  public final SyntheticKind CONST_DYNAMIC = generator.forInstanceClass("$Condy");

  // Method synthetics.
  public final SyntheticKind ENUM_UNBOXING_CHECK_NOT_ZERO_METHOD =
      generator.forSingleMethod("CheckNotZero");
  public final SyntheticKind RECORD_HELPER = generator.forSingleMethod("Record");
  public final SyntheticKind BACKPORT = generator.forSingleMethod("Backport");
  public final SyntheticKind BACKPORT_WITH_FORWARDING =
      generator.forSingleMethod("BackportWithForwarding");
  public final SyntheticKind STATIC_INTERFACE_CALL =
      generator.forSingleMethod("StaticInterfaceCall");
  public final SyntheticKind TO_STRING_IF_NOT_NULL = generator.forSingleMethod("ToStringIfNotNull");
  public final SyntheticKind THROW_CCE_IF_NOT_NULL = generator.forSingleMethod("ThrowCCEIfNotNull");
  public final SyntheticKind THROW_IAE = generator.forSingleMethod("ThrowIAE");
  public final SyntheticKind THROW_ICCE = generator.forSingleMethod("ThrowICCE");
  public final SyntheticKind THROW_NSME = generator.forSingleMethod("ThrowNSME");
  public final SyntheticKind THROW_RTE = generator.forSingleMethod("ThrowRTE");
  public final SyntheticKind TWR_CLOSE_RESOURCE = generator.forSingleMethod("TwrCloseResource");
  public final SyntheticKind SERVICE_LOADER = generator.forSingleMethod("ServiceLoad");
  public final SyntheticKind OUTLINE = generator.forSingleMethod("Outline");
  public final SyntheticKind COVARIANT_OUTLINE = generator.forSingleMethod("CovariantOutline");
  public final SyntheticKind API_CONVERSION = generator.forSingleMethod("APIConversion");
  public final SyntheticKind API_CONVERSION_PARAMETERS =
      generator.forSingleMethod("APIConversionParameters");
  public final SyntheticKind COLLECTION_CONVERSION =
      generator.forSingleMethod("$CollectionConversion");
  public final SyntheticKind API_MODEL_OUTLINE = generator.forSingleMethod("ApiModelOutline");

  private final List<SyntheticKind> ALL_KINDS;
  private String lazyVersionHash = null;

  public SyntheticNaming() {
    ALL_KINDS = generator.getAllKinds();
    generator = null;
  }

  public String getVersionHash() {
    if (lazyVersionHash == null) {
      computeVersionHash();
    }
    return lazyVersionHash;
  }

  private void computeVersionHash() {
    Hasher hasher = Hashing.sha256().newHasher();
    hasher.putString(Version.getVersionString(), StandardCharsets.UTF_8);
    for (SyntheticKind kind : ALL_KINDS) {
      kind.hash(hasher);
    }
    lazyVersionHash = hasher.hash().toString();
  }

  public Collection<SyntheticKind> kinds() {
    return ALL_KINDS;
  }

  public SyntheticKind fromId(int id) {
    if (0 < id && id <= ALL_KINDS.size()) {
      return ALL_KINDS.get(id - 1);
    }
    return null;
  }

  private static class KindGenerator {
    private int nextId = 1;
    private List<SyntheticKind> kinds = new ArrayList<>();

    private SyntheticKind register(SyntheticKind kind) {
      kinds.add(kind);
      if (kinds.size() != kind.getId()) {
        throw new Unreachable("Invalid synthetic kind id: " + kind.getId());
      }
      return kind;
    }

    private int getNextId() {
      return nextId++;
    }

    SyntheticKind forSingleMethod(String descriptor) {
      return register(new SyntheticMethodKind(getNextId(), descriptor));
    }

    // TODO(b/214901256): Remove once fixed.
    SyntheticKind forNonSharableInstanceClass(String descriptor) {
      return register(new SyntheticClassKind(getNextId(), descriptor, false));
    }

    SyntheticKind forInstanceClass(String descriptor) {
      return register(new SyntheticClassKind(getNextId(), descriptor, true));
    }

    SyntheticKind forFixedClass(String descriptor) {
      return register(new SyntheticFixedClassKind(getNextId(), descriptor, false));
    }

    SyntheticKind forGlobalClass() {
      return register(new SyntheticFixedClassKind(getNextId(), "", true));
    }

    SyntheticKind forGlobalClasspathClass() {
      return register(new SyntheticFixedClassKind(getNextId(), "", false));
    }

    List<SyntheticKind> getAllKinds() {
      List<SyntheticKind> kinds = this.kinds;
      this.kinds = null;
      return kinds;
    }
  }

  /**
   * Enumeration of all kinds of synthetic items.
   *
   * <p>The synthetic kinds are used to provide hinting about what a synthetic item represents. The
   * kinds must *not* be used be the compiler and are only meant for "debugging". The compiler and
   * its test may use the kind information as part of asserting properties of the compiler. The kind
   * will be put into any non-minified synthetic name and thus the kind "descriptor" must be a
   * distinct for each kind.
   */
  public abstract static class SyntheticKind implements Ordered<SyntheticKind> {

    private final int id;
    private final String descriptor;

    SyntheticKind(int id, String descriptor) {
      this.id = id;
      this.descriptor = descriptor;
    }

    @Override
    public int compareTo(SyntheticKind other) {
      return Integer.compare(id, other.getId());
    }

    @Override
    public int hashCode() {
      return id;
    }

    @Override
    public boolean equals(Object o) {
      return Equatable.equalsImpl(this, o);
    }

    public int getId() {
      return id;
    }

    public String getDescriptor() {
      return descriptor;
    }

    public abstract boolean isShareable();

    public abstract boolean isSingleSyntheticMethod();

    public abstract boolean isFixedSuffixSynthetic();

    public abstract boolean isGlobal();

    public abstract boolean isMayOverridesNonProgramType();

    public final void hash(Hasher hasher) {
      hasher.putInt(getId());
      hasher.putString(getDescriptor(), StandardCharsets.UTF_8);
      internalHash(hasher);
    }

    public abstract void internalHash(Hasher hasher);
  }

  private static class SyntheticMethodKind extends SyntheticKind {

    public SyntheticMethodKind(int id, String descriptor) {
      super(id, descriptor);
    }

    @Override
    public boolean isShareable() {
      // Single methods may always be shared.
      return true;
    }

    @Override
    public boolean isSingleSyntheticMethod() {
      return true;
    }

    @Override
    public boolean isFixedSuffixSynthetic() {
      return false;
    }

    @Override
    public boolean isGlobal() {
      return false;
    }

    @Override
    public boolean isMayOverridesNonProgramType() {
      return false;
    }

    @Override
    public void internalHash(Hasher hasher) {
      hasher.putString("method", StandardCharsets.UTF_8);
    }
  }

  private static class SyntheticClassKind extends SyntheticKind {

    // TODO(b/214901256): Remove once fixed.
    private final boolean sharable;

    public SyntheticClassKind(int id, String descriptor, boolean sharable) {
      super(id, descriptor);
      this.sharable = sharable;
    }

    @Override
    public boolean isShareable() {
      return sharable;
    }

    @Override
    public final boolean isSingleSyntheticMethod() {
      return false;
    }

    @Override
    public boolean isFixedSuffixSynthetic() {
      return false;
    }

    @Override
    public boolean isGlobal() {
      return false;
    }

    @Override
    public boolean isMayOverridesNonProgramType() {
      return false;
    }

    @Override
    public void internalHash(Hasher hasher) {
      hasher.putString("class", StandardCharsets.UTF_8);
      hasher.putBoolean(sharable);
    }
  }

  private static class SyntheticFixedClassKind extends SyntheticClassKind {
    private final boolean mayOverridesNonProgramType;

    private SyntheticFixedClassKind(int id, String descriptor, boolean mayOverridesNonProgramType) {
      super(id, descriptor, false);
      this.mayOverridesNonProgramType = mayOverridesNonProgramType;
    }

    @Override
    public boolean isShareable() {
      return false;
    }

    @Override
    public boolean isFixedSuffixSynthetic() {
      return true;
    }

    @Override
    public boolean isGlobal() {
      return getDescriptor().isEmpty();
    }

    @Override
    public boolean isMayOverridesNonProgramType() {
      return mayOverridesNonProgramType;
    }

    @Override
    public void internalHash(Hasher hasher) {
      hasher.putString(isGlobal() ? "global" : "fixed", StandardCharsets.UTF_8);
      hasher.putBoolean(mayOverridesNonProgramType);
    }
  }

  public static final String COMPANION_CLASS_SUFFIX = "$-CC";
  private static final String SYNTHETIC_CLASS_SEPARATOR = "$$";
  /**
   * The internal synthetic class separator is only used for representing synthetic items during
   * compilation. In particular, this separator must never be used to write synthetic classes to the
   * final compilation result.
   */
  private static final String INTERNAL_SYNTHETIC_CLASS_SEPARATOR =
      SYNTHETIC_CLASS_SEPARATOR + "InternalSynthetic";
  /**
   * The external synthetic class separator is used when writing classes. It may appear in types
   * during compilation as the output of a compilation may be the input to another.
   */
  public static final String EXTERNAL_SYNTHETIC_CLASS_SEPARATOR =
      SYNTHETIC_CLASS_SEPARATOR + "ExternalSynthetic";
  /** Method name when generating synthetic methods in a class. */
  static final String INTERNAL_SYNTHETIC_METHOD_NAME = "m";

  static String getPrefixForExternalSyntheticType(SyntheticKind kind, DexType type) {
    String binaryName = type.toBinaryName();
    if (kind.isGlobal()) {
      return binaryName;
    }
    int index =
        binaryName.lastIndexOf(
            kind.isFixedSuffixSynthetic() ? kind.descriptor : SYNTHETIC_CLASS_SEPARATOR);
    if (index < 0) {
      throw new Unreachable("Unexpected failure to compute a synthetic prefix for " + binaryName);
    }
    return binaryName.substring(0, index);
  }

  static DexType createFixedType(
      SyntheticKind kind, SynthesizingContext context, DexItemFactory factory) {
    assert kind.isFixedSuffixSynthetic();
    return createType("", kind, context.getSynthesizingContextType(), "", factory);
  }

  static DexType createInternalType(
      SyntheticKind kind, SynthesizingContext context, String id, DexItemFactory factory) {
    assert !kind.isFixedSuffixSynthetic();
    return createType(
        INTERNAL_SYNTHETIC_CLASS_SEPARATOR,
        kind,
        context.getSynthesizingContextType(),
        id,
        factory);
  }

  static DexType createExternalType(
      SyntheticKind kind, String externalSyntheticTypePrefix, String id, DexItemFactory factory) {
    assert kind.isFixedSuffixSynthetic() == id.isEmpty();
    return createType(
        kind.isFixedSuffixSynthetic() ? "" : EXTERNAL_SYNTHETIC_CLASS_SEPARATOR,
        kind,
        externalSyntheticTypePrefix,
        id,
        factory);
  }

  private static DexType createType(
      String separator, SyntheticKind kind, DexType context, String id, DexItemFactory factory) {
    return factory.createType(createDescriptor(separator, kind, context.getInternalName(), id));
  }

  private static DexType createType(
      String separator,
      SyntheticKind kind,
      String externalSyntheticTypePrefix,
      String id,
      DexItemFactory factory) {
    return factory.createType(createDescriptor(separator, kind, externalSyntheticTypePrefix, id));
  }

  public static String createDescriptor(
      String separator, SyntheticKind kind, String externalSyntheticTypePrefix, String id) {
    return DescriptorUtils.getDescriptorFromClassBinaryName(
        externalSyntheticTypePrefix + separator + kind.descriptor + id);
  }

  public static boolean verifyNotInternalSynthetic(DexType type) {
    return verifyNotInternalSynthetic(type.toDescriptorString());
  }

  public static boolean verifyNotInternalSynthetic(ClassReference reference) {
    return verifyNotInternalSynthetic(reference.getDescriptor());
  }

  public static boolean verifyNotInternalSynthetic(String typeBinaryNameOrDescriptor) {
    assert !typeBinaryNameOrDescriptor.contains(INTERNAL_SYNTHETIC_CLASS_SEPARATOR)
        : typeBinaryNameOrDescriptor;
    return true;
  }

  // Visible via package protection in SyntheticItemsTestUtils.

  enum Phase {
    INTERNAL,
    EXTERNAL
  }

  static String getPhaseSeparator(Phase phase) {
    assert phase != null;
    return phase == Phase.INTERNAL
        ? INTERNAL_SYNTHETIC_CLASS_SEPARATOR
        : EXTERNAL_SYNTHETIC_CLASS_SEPARATOR;
  }

  static ClassReference makeSyntheticReferenceForTest(
      ClassReference context, SyntheticKind kind, String id) {
    return Reference.classFromDescriptor(
        createDescriptor(EXTERNAL_SYNTHETIC_CLASS_SEPARATOR, kind, context.getBinaryName(), id));
  }

  static boolean isSynthetic(ClassReference clazz, Phase phase, SyntheticKind kind) {
    String typeName = clazz.getTypeName();
    if (kind.isFixedSuffixSynthetic()) {
      assert phase == null;
      return clazz.getBinaryName().endsWith(kind.descriptor);
    }
    String separator = getPhaseSeparator(phase);
    int i = typeName.lastIndexOf(separator);
    return i >= 0 && checkMatchFrom(kind, typeName, i, separator, phase == Phase.EXTERNAL);
  }

  private static boolean checkMatchFrom(
      SyntheticKind kind,
      String name,
      int i,
      String externalSyntheticClassSeparator,
      boolean checkIntSuffix) {
    int end = i + externalSyntheticClassSeparator.length() + kind.descriptor.length();
    if (end >= name.length()) {
      return false;
    }
    String prefix = name.substring(i, end);
    return prefix.equals(externalSyntheticClassSeparator + kind.descriptor)
        && (!checkIntSuffix || isInt(name.substring(end)));
  }

  private static boolean isInt(String str) {
    if (str.isEmpty()) {
      return false;
    }
    if ('0' == str.charAt(0)) {
      return str.length() == 1;
    }
    for (int i = 0; i < str.length(); i++) {
      if (!Character.isDigit(str.charAt(i))) {
        return false;
      }
    }
    return true;
  }
}
