// 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.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 it.unimi.dsi.fastutil.ints.IntArraySet;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class SyntheticNaming {

  public SyntheticNaming() {}

  private KindGenerator generator = new KindGenerator();

  // Global synthetics.
  public final SyntheticKind RECORD_TAG = generator.forGlobalClass(1);
  public final SyntheticKind API_MODEL_STUB = generator.forGlobalClass(33);

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

  // Fixed suffix synthetics. Each has a hygienic prefix type.
  public final SyntheticKind ENUM_UNBOXING_LOCAL_UTILITY_CLASS =
      generator.forFixedClass(24, "$EnumUnboxingLocalUtility");
  public final SyntheticKind ENUM_UNBOXING_SHARED_UTILITY_CLASS =
      generator.forFixedClass(25, "$EnumUnboxingSharedUtility");
  public final SyntheticKind COMPANION_CLASS = generator.forFixedClass(2, "$-CC");
  public final SyntheticKind EMULATED_INTERFACE_CLASS =
      generator.forFixedClass(3, InterfaceDesugaringForTesting.EMULATED_INTERFACE_CLASS_SUFFIX);
  public final SyntheticKind RETARGET_CLASS = generator.forFixedClass(20, "RetargetClass");
  public final SyntheticKind RETARGET_INTERFACE = generator.forFixedClass(21, "RetargetInterface");
  public final SyntheticKind WRAPPER = generator.forFixedClass(22, "$Wrapper");
  public final SyntheticKind VIVIFIED_WRAPPER = generator.forFixedClass(23, "$VivifiedWrapper");
  public final SyntheticKind INIT_TYPE_ARGUMENT = generator.forFixedClass(5, "-IA");
  public final SyntheticKind HORIZONTAL_INIT_TYPE_ARGUMENT_1 =
      generator.forFixedClass(6, SYNTHETIC_CLASS_SEPARATOR + "IA$1");
  public final SyntheticKind HORIZONTAL_INIT_TYPE_ARGUMENT_2 =
      generator.forFixedClass(7, SYNTHETIC_CLASS_SEPARATOR + "IA$2");
  public final SyntheticKind HORIZONTAL_INIT_TYPE_ARGUMENT_3 =
      generator.forFixedClass(8, SYNTHETIC_CLASS_SEPARATOR + "IA$3");
  public final SyntheticKind ENUM_CONVERSION = generator.forFixedClass(31, "$EnumConversion");

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

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

  // Method synthetics.
  public final SyntheticKind ENUM_UNBOXING_CHECK_NOT_ZERO_METHOD =
      generator.forSingleMethod(27, "CheckNotZero");
  public final SyntheticKind RECORD_HELPER = generator.forSingleMethod(9, "Record");
  public final SyntheticKind BACKPORT = generator.forSingleMethod(10, "Backport");
  public final SyntheticKind BACKPORT_WITH_FORWARDING =
      generator.forSingleMethod(34, "BackportWithForwarding");
  public final SyntheticKind STATIC_INTERFACE_CALL =
      generator.forSingleMethod(11, "StaticInterfaceCall");
  public final SyntheticKind TO_STRING_IF_NOT_NULL =
      generator.forSingleMethod(12, "ToStringIfNotNull");
  public final SyntheticKind THROW_CCE_IF_NOT_NULL =
      generator.forSingleMethod(13, "ThrowCCEIfNotNull");
  public final SyntheticKind THROW_IAE = generator.forSingleMethod(14, "ThrowIAE");
  public final SyntheticKind THROW_ICCE = generator.forSingleMethod(15, "ThrowICCE");
  public final SyntheticKind THROW_NSME = generator.forSingleMethod(16, "ThrowNSME");
  public final SyntheticKind TWR_CLOSE_RESOURCE = generator.forSingleMethod(17, "TwrCloseResource");
  public final SyntheticKind SERVICE_LOADER = generator.forSingleMethod(18, "ServiceLoad");
  public final SyntheticKind OUTLINE = generator.forSingleMethod(19, "Outline");
  public final SyntheticKind API_CONVERSION = generator.forSingleMethod(26, "APIConversion");
  public final SyntheticKind API_CONVERSION_PARAMETERS =
      generator.forSingleMethod(28, "APIConversionParameters");
  public final SyntheticKind ARRAY_CONVERSION = generator.forSingleMethod(37, "$ArrayConversion");
  public final SyntheticKind API_MODEL_OUTLINE = generator.forSingleMethod(32, "ApiModelOutline");

  private final List<SyntheticKind> ALL_KINDS = generator.getAllKinds();

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

  public SyntheticKind fromId(int id) {
    for (SyntheticKind kind : ALL_KINDS) {
      if (kind.getId() == id) {
        return kind;
      }
    }
    return null;
  }

  private static class KindGenerator {
    private List<SyntheticKind> kinds = new ArrayList<>();
    private IntSet usedIds = new IntArraySet();

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

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

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

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

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

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

    SyntheticKind forGlobalClasspathClass(int id) {
      return register(new SyntheticFixedClassKind(id, "", 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();

  }

  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;
    }

  }

  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;
    }

  }

  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;
    }

  }

  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.
   */
  private 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));
  }

  private 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);
    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;
  }
}
