// Copyright (c) 2016, 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.graph;

import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.graph.DexValue.DexValueAnnotation;
import com.android.tools.r8.graph.DexValue.DexValueArray;
import com.android.tools.r8.graph.DexValue.DexValueByte;
import com.android.tools.r8.graph.DexValue.DexValueInt;
import com.android.tools.r8.graph.DexValue.DexValueMethod;
import com.android.tools.r8.graph.DexValue.DexValueNull;
import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.graph.DexValue.DexValueType;
import com.android.tools.r8.graph.GenericSignature.FieldTypeSignature;
import com.android.tools.r8.ir.desugar.CovariantReturnTypeAnnotationTransformer;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.synthesis.SyntheticItems;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.structural.StructuralItem;
import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;

public class DexAnnotation extends DexItem implements StructuralItem<DexAnnotation> {

  public enum AnnotatedKind {
    FIELD,
    METHOD,
    TYPE,
    PARAMETER;

    public static AnnotatedKind from(DexDefinition definition) {
      return from(definition.getReference());
    }

    public static AnnotatedKind from(ProgramDefinition definition) {
      return from(definition.getReference());
    }

    public static AnnotatedKind from(DexReference reference) {
      return reference.apply(type -> TYPE, field -> FIELD, method -> METHOD);
    }

    public boolean isMethod() {
      return this == METHOD;
    }

    public boolean isParameter() {
      return this == PARAMETER;
    }
  }

  public static final DexAnnotation[] EMPTY_ARRAY = {};
  public static final int VISIBILITY_BUILD = 0x00;
  public static final int VISIBILITY_RUNTIME = 0x01;
  public static final int VISIBILITY_SYSTEM = 0x02;
  public final int visibility;
  public final DexEncodedAnnotation annotation;

  private static final int UNKNOWN_API_LEVEL = -1;
  private static final int NOT_SET_API_LEVEL = -2;

  protected static void specify(StructuralSpecification<DexAnnotation, ?> spec) {
    spec.withItem(a -> a.annotation).withInt(a -> a.visibility);
  }

  public DexAnnotation(int visibility, DexEncodedAnnotation annotation) {
    this.visibility = visibility;
    this.annotation = annotation;
  }

  public boolean isTypeAnnotation() {
    return false;
  }

  public DexTypeAnnotation asTypeAnnotation() {
    return null;
  }

  @Override
  public DexAnnotation self() {
    return this;
  }

  @Override
  public StructuralMapping<DexAnnotation> getStructuralMapping() {
    return DexAnnotation::specify;
  }

  public DexType getAnnotationType() {
    return annotation.type;
  }

  @Override
  public int hashCode() {
    return visibility + annotation.hashCode() * 3;
  }

  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    }
    if (other instanceof DexAnnotation) {
      DexAnnotation o = (DexAnnotation) other;
      return (visibility == o.visibility) && annotation.equals(o.annotation);
    }
    return false;
  }

  @Override
  public String toString() {
    return visibility + " " + annotation;
  }

  public int getVisibility() {
    return visibility;
  }

  public void collectIndexedItems(AppView<?> appView, IndexedItemCollection indexedItems) {
    annotation.collectIndexedItems(appView, indexedItems);
  }

  @Override
  protected void collectMixedSectionItems(MixedSectionCollection mixedItems) {
    mixedItems.add(this);
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean retainCompileTimeAnnotation(DexType annotation, InternalOptions options) {
    if (options.retainCompileTimeAnnotations) {
      return true;
    }
    if (annotation == options.itemFactory.annotationSynthesizedClass
        || annotation
            .getDescriptor()
            .startsWith(options.itemFactory.dalvikAnnotationOptimizationPrefix)) {
      return true;
    }
    if (options.processCovariantReturnTypeAnnotations) {
      // @CovariantReturnType annotations are processed by CovariantReturnTypeAnnotationTransformer,
      // they thus need to be read here and will then be removed as part of the processing.
      return CovariantReturnTypeAnnotationTransformer.isCovariantReturnTypeAnnotation(
          annotation, options.itemFactory);
    }
    return false;
  }

  public static DexAnnotation createEnclosingClassAnnotation(DexType enclosingClass,
      DexItemFactory factory) {
    return createSystemValueAnnotation(factory.annotationEnclosingClass, factory,
        new DexValueType(enclosingClass));
  }

  public static DexType getEnclosingClassFromAnnotation(
      DexAnnotation annotation, DexItemFactory factory) {
    DexValue value = getSystemValueAnnotationValue(factory.annotationEnclosingClass, annotation);
    if (value == null) {
      return null;
    }
    return value.asDexValueType().value;
  }

  public static DexAnnotation createEnclosingMethodAnnotation(DexMethod enclosingMethod,
      DexItemFactory factory) {
    return createSystemValueAnnotation(factory.annotationEnclosingMethod, factory,
        new DexValueMethod(enclosingMethod));
  }

  public static DexMethod getEnclosingMethodFromAnnotation(
      DexAnnotation annotation, DexItemFactory factory) {
    DexValue value = getSystemValueAnnotationValue(factory.annotationEnclosingMethod, annotation);
    if (value == null) {
      return null;
    }
    return value.asDexValueMethod().value;
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isEnclosingClassAnnotation(
      DexAnnotation annotation, DexItemFactory factory) {
    return annotation.annotation.type == factory.annotationEnclosingClass;
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isEnclosingMethodAnnotation(
      DexAnnotation annotation, DexItemFactory factory) {
    return annotation.annotation.type == factory.annotationEnclosingMethod;
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isInnerClassAnnotation(DexAnnotation annotation, DexItemFactory factory) {
    return annotation.annotation.type == factory.annotationInnerClass;
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isMemberClassesAnnotation(
      DexAnnotation annotation, DexItemFactory factory) {
    return annotation.annotation.type == factory.annotationMemberClasses;
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isNestHostAnnotation(DexAnnotation annotation, DexItemFactory factory) {
    return annotation.annotation.type == factory.annotationNestHost;
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isNestMembersAnnotation(DexAnnotation annotation, DexItemFactory factory) {
    return annotation.annotation.type == factory.annotationNestMembers;
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isPermittedSubclassesAnnotation(
      DexAnnotation annotation, DexItemFactory factory) {
    return annotation.annotation.type == factory.annotationPermittedSubclasses;
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isRecordAnnotation(DexAnnotation annotation, DexItemFactory factory) {
    return annotation.getAnnotationType() == factory.annotationRecord;
  }

  public static DexAnnotation createInnerClassAnnotation(
      DexString clazz, int access, DexItemFactory factory) {
    return new DexAnnotation(
        VISIBILITY_SYSTEM,
        new DexEncodedAnnotation(
            factory.annotationInnerClass,
            new DexAnnotationElement[] {
              new DexAnnotationElement(
                  factory.createString("accessFlags"), DexValueInt.create(access)),
              new DexAnnotationElement(
                  factory.createString("name"),
                  (clazz == null) ? DexValueNull.NULL : new DexValueString(clazz))
            }));
  }

  @SuppressWarnings("ReferenceEquality")
  public static Pair<DexString, Integer> getInnerClassFromAnnotation(
      DexAnnotation annotation, DexItemFactory factory) {
    assert isInnerClassAnnotation(annotation, factory);
    DexAnnotationElement[] elements = annotation.annotation.elements;
    Pair<DexString, Integer> result = new Pair<>();
    for (DexAnnotationElement element : elements) {
      if (element.name == factory.createString("name")) {
        if (element.value.isDexValueString()) {
          result.setFirst(element.value.asDexValueString().getValue());
        }
      } else {
        assert element.name == factory.createString("accessFlags");
        result.setSecond(element.value.asDexValueInt().getValue());
      }
    }
    return result;
  }

  public static DexAnnotation createMemberClassesAnnotation(List<DexType> classes,
      DexItemFactory factory) {
    DexValue[] values = new DexValue[classes.size()];
    for (int i = 0; i < classes.size(); i++) {
      values[i] = new DexValueType(classes.get(i));
    }
    return createSystemValueAnnotation(factory.annotationMemberClasses, factory,
        new DexValueArray(values));
  }

  public static List<DexType> getMemberClassesFromAnnotation(
      DexAnnotation annotation, DexItemFactory factory) {
    DexValue value = getSystemValueAnnotationValue(factory.annotationMemberClasses, annotation);
    if (value == null) {
      return null;
    }
    DexValueArray membersArray = value.asDexValueArray();
    List<DexType> types = new ArrayList<>(membersArray.getValues().length);
    for (DexValue elementValue : membersArray.getValues()) {
      types.add(elementValue.asDexValueType().value);
    }
    return types;
  }

  public static DexType getNestHostFromAnnotation(
      DexAnnotation annotation, DexItemFactory factory) {
    DexValue value = getSystemValueAnnotationValue(factory.annotationNestHost, annotation);
    if (value == null) {
      return null;
    }
    return value.asDexValueType().getValue();
  }

  private static List<DexType> getTypesFromAnnotation(
      DexType annotationType, DexAnnotation annotation) {
    DexValue value = getSystemValueAnnotationValue(annotationType, annotation);
    if (value == null) {
      return null;
    }
    DexValueArray membersArray = value.asDexValueArray();
    List<DexType> types = new ArrayList<>(membersArray.getValues().length);
    for (DexValue elementValue : membersArray.getValues()) {
      types.add(elementValue.asDexValueType().value);
    }
    return types;
  }

  public static List<DexType> getNestMembersFromAnnotation(
      DexAnnotation annotation, DexItemFactory factory) {
    return getTypesFromAnnotation(factory.annotationNestMembers, annotation);
  }

  public static List<DexType> getPermittedSubclassesFromAnnotation(
      DexAnnotation annotation, DexItemFactory factory) {
    return getTypesFromAnnotation(factory.annotationPermittedSubclasses, annotation);
  }

  /** See {@link #createRecordAnnotation(DexProgramClass, AppView)} for the representation. */
  public static List<RecordComponentInfo> getRecordComponentInfoFromAnnotation(
      DexType type, DexAnnotation annotation, DexItemFactory factory, Origin origin) {
    DexValue componentNamesValue =
        getSystemValueAnnotationValueWithName(
            factory.annotationRecord, annotation, factory.annotationRecordComponentNames);
    DexValue componentTypesValue =
        getSystemValueAnnotationValueWithName(
            factory.annotationRecord, annotation, factory.annotationRecordComponentTypes);
    DexValue componentSignaturesValue =
        getSystemValueAnnotationValueWithName(
            factory.annotationRecord, annotation, factory.annotationRecordComponentSignatures);
    DexValue componentAnnotationVisibilitiesValue =
        getSystemValueAnnotationValueWithName(
            factory.annotationRecord,
            annotation,
            factory.annotationRecordComponentAnnotationVisibilities);
    DexValue componentAnnotationsValue =
        getSystemValueAnnotationValueWithName(
            factory.annotationRecord, annotation, factory.annotationRecordComponentAnnotations);

    if (componentNamesValue == null
        || componentTypesValue == null
        || componentSignaturesValue == null
        || componentAnnotationVisibilitiesValue == null
        || componentAnnotationsValue == null) {
      return null;
    }
    if (!componentNamesValue.isDexValueArray()
        || !componentTypesValue.isDexValueArray()
        || !componentSignaturesValue.isDexValueArray()
        || !componentAnnotationVisibilitiesValue.isDexValueArray()
        || !componentAnnotationsValue.isDexValueArray()) {
      return null;
    }
    DexValueArray componentNamesValueArray = componentNamesValue.asDexValueArray();
    DexValueArray componentTypesValueArray = componentTypesValue.asDexValueArray();
    DexValueArray componentSignaturesValueArray = componentSignaturesValue.asDexValueArray();
    DexValueArray componentAnnotationVisibilitiesValueArray =
        componentAnnotationVisibilitiesValue.asDexValueArray();
    DexValueArray componentAnnotationsValueArray = componentAnnotationsValue.asDexValueArray();
    if (componentNamesValueArray.size() != componentTypesValueArray.size()
        || componentNamesValueArray.size() != componentSignaturesValueArray.size()
        || componentNamesValueArray.size() != componentAnnotationVisibilitiesValueArray.size()
        || componentNamesValueArray.size() != componentAnnotationsValueArray.size()) {
      return null;
    }
    List<RecordComponentInfo> result = new ArrayList<>(componentNamesValueArray.size());
    for (int componentIndex = 0;
        componentIndex < componentNamesValueArray.size();
        componentIndex++) {
      DexValue nameValue = componentNamesValueArray.getValue(componentIndex);
      DexValue typeValue = componentTypesValueArray.getValue(componentIndex);
      DexValue signatureValue = componentSignaturesValueArray.getValue(componentIndex);
      DexValue visibilitiesValue =
          componentAnnotationVisibilitiesValueArray.getValue(componentIndex);
      DexValue annotationsValue = componentAnnotationsValueArray.getValue(componentIndex);
      if (!nameValue.isDexValueString()
          || !typeValue.isDexValueType()
          || !(signatureValue.isDexValueAnnotation() || signatureValue.isDexValueNull())
          || !visibilitiesValue.isDexValueArray()
          || !annotationsValue.isDexValueArray()) {
        return null;
      }
      DexValueArray visibilitiesValueArray = visibilitiesValue.asDexValueArray();
      DexValueArray annotationsValueArray = annotationsValue.asDexValueArray();
      if (visibilitiesValueArray.size() != annotationsValueArray.size()) {
        return null;
      }
      List<DexAnnotation> componentAnnotations = Collections.emptyList();
      if (annotationsValueArray.size() > 0) {
        componentAnnotations = new ArrayList<>(annotationsValueArray.size());
        for (int annotationIndex = 0;
            annotationIndex < annotationsValueArray.size();
            annotationIndex++) {
          DexValue visibilityValue = visibilitiesValueArray.getValue(annotationIndex);
          DexValue annotationValue = annotationsValueArray.getValue(annotationIndex);
          if (!visibilityValue.isDexValueByte() || !annotationValue.isDexValueAnnotation()) {
            return null;
          }
          componentAnnotations.add(
              new DexAnnotation(
                  visibilityValue.asDexValueByte().getValue(),
                  annotationValue.asDexValueAnnotation().getValue()));
        }
      }
      FieldTypeSignature componentSignature =
          GenericSignature.parseFieldTypeSignature(
              nameValue.asDexValueString().getValue().toString(),
              signatureValue.isDexValueAnnotation()
                  ? getSignature(signatureValue.asDexValueAnnotation().getValue())
                  : null,
              origin,
              factory,
              null);

      DexType componentType = typeValue.asDexValueType().getValue();
      DexString componentName = nameValue.asDexValueString().getValue();
      DexField componentField = factory.createField(type, componentType, componentName);
      result.add(new RecordComponentInfo(componentField, componentSignature, componentAnnotations));
    }
    return result;
  }

  public static DexAnnotation createSourceDebugExtensionAnnotation(DexValue value,
      DexItemFactory factory) {
    return new DexAnnotation(VISIBILITY_SYSTEM,
        new DexEncodedAnnotation(factory.annotationSourceDebugExtension,
            new DexAnnotationElement[] {
              new DexAnnotationElement(factory.createString("value"), value)
            }));
  }

  public static DexAnnotation createMethodParametersAnnotation(DexValue[] names,
      DexValue[] accessFlags, DexItemFactory factory) {
    assert names.length == accessFlags.length;
    return new DexAnnotation(VISIBILITY_SYSTEM,
        new DexEncodedAnnotation(factory.annotationMethodParameters,
            new DexAnnotationElement[]{
                new DexAnnotationElement(
                    factory.createString("names"),
                    new DexValueArray(names)),
                new DexAnnotationElement(
                    factory.createString("accessFlags"),
                    new DexValueArray(accessFlags))
            }));
  }

  public static DexAnnotation createAnnotationDefaultAnnotation(DexType type,
      List<DexAnnotationElement> defaults, DexItemFactory factory) {
    return createSystemValueAnnotation(factory.annotationDefault, factory,
        new DexValueAnnotation(
            new DexEncodedAnnotation(type,
                defaults.toArray(DexAnnotationElement.EMPTY_ARRAY)))
    );
  }

  public static DexAnnotation createSignatureAnnotation(String signature, DexItemFactory factory) {
    return createSystemValueAnnotation(factory.annotationSignature, factory,
        compressSignature(signature, factory));
  }

  public static DexAnnotation createNestHostAnnotation(
      NestHostClassAttribute host, DexItemFactory factory) {
    return createSystemValueAnnotation(
        factory.annotationNestHost, factory, new DexValue.DexValueType(host.getNestHost()));
  }

  public static DexAnnotation createNestMembersAnnotation(
      List<NestMemberClassAttribute> members, DexItemFactory factory) {
    List<DexValueType> list = new ArrayList<>(members.size());
    for (NestMemberClassAttribute member : members) {
      list.add(new DexValue.DexValueType(member.getNestMember()));
    }
    return createSystemValueAnnotation(
        factory.annotationNestMembers,
        factory,
        new DexValue.DexValueArray(list.toArray(DexValue.EMPTY_ARRAY)));
  }

  public static DexAnnotation createPermittedSubclassesAnnotation(
      List<PermittedSubclassAttribute> permittedSubclasses, DexItemFactory factory) {
    List<DexValueType> list = new ArrayList<>(permittedSubclasses.size());
    for (PermittedSubclassAttribute permittedSubclass : permittedSubclasses) {
      list.add(new DexValue.DexValueType(permittedSubclass.getPermittedSubclass()));
    }
    return createSystemValueAnnotation(
        factory.annotationPermittedSubclasses,
        factory,
        new DexValue.DexValueArray(list.toArray(DexValue.EMPTY_ARRAY)));
  }

  /**
   * Record component information is written to DEX as a system annotation named <code>
   * dalvik.annotation.Record</code> with the following content:
   *
   * <pre>
   *   componentAnnotationVisibilities byte[][]
   *   componentAnnotations Annotation[][]
   *   componentNames String[]
   *   componentSignatures Annotation[]  // Annotation dalvik.annotation.Signature or NULL
   *   componentTypes String[]
   * </pre>
   *
   * Each of the arrays have one element for each component.
   *
   * <p>Example of a two component record with two annotations on the first component and one on the
   * second and with a signature on the first component.
   *
   * <pre>
   * .annotation system Ldalvik/annotation/Record;
   *   componentAnnotationVisibilities = {
   *     {
   *       0x1,
   *       0x1
   *     },
   *     {
   *       0x1
   *     }
   *   }
   *   componentAnnotations = {
   *     {
   *       .subannotation LAnnotation1;
   *         value = "a"
   *       .end subannotation,
   *       .subannotation LAnnotation2;
   *         value = "c"
   *       .end subannotation
   *     },
   *     {
   *       .subannotation LAnnotation3;
   *         value = "z"
   *       .end subannotation
   *     }
   *   }
   *   componentNames = {
   *      "name",
   *      "age"
   *   }
   *   componentSignatures = {
   *     .subannotation Ldalvik/annotation/Signature;
   *       value = {
   *         "TX;"
   *       }
   *     .end subannotation,
   *     NULL
   *   }
   *   componentTypes = {
   *     Ljava/lang/CharSequence;,
   *     Ljava/lang/Object;
   *   }
   * .end annotation
   * </pre>
   */
  public static DexAnnotation createRecordAnnotation(DexProgramClass clazz, AppView<?> appView) {
    DexItemFactory factory = appView.dexItemFactory();
    int componentCount = clazz.getRecordComponents().size();
    DexValueString[] componentNames = new DexValueString[componentCount];
    DexValueType[] componentTypes = new DexValueType[componentCount];
    DexValue[] componentSignatures = new DexValue[componentCount];
    DexValueArray[] componentAnnotationVisibilities = new DexValueArray[componentCount];
    DexValueArray[] componentAnnotations = new DexValueArray[componentCount];
    for (int componentIndex = 0; componentIndex < componentCount; componentIndex++) {
      RecordComponentInfo info = clazz.getRecordComponents().get(componentIndex);
      componentNames[componentIndex] =
          new DexValueString(appView.getNamingLens().lookupName(info.getField()));
      componentTypes[componentIndex] = new DexValueType(info.getType());
      if (info.getSignature().hasNoSignature()) {
        componentSignatures[componentIndex] = DexValueNull.NULL;
      } else {
        componentSignatures[componentIndex] =
            new DexValueAnnotation(
                createSignatureAnnotation(info.getSignature().toString(), factory).annotation);
      }
      int annotationsSize = info.getAnnotations().size();
      DexValueByte[] visibilities = new DexValueByte[annotationsSize];
      DexValueAnnotation[] annotations = new DexValueAnnotation[annotationsSize];
      componentAnnotationVisibilities[componentIndex] = new DexValueArray(visibilities);
      componentAnnotations[componentIndex] = new DexValueArray(annotations);
      for (int annotationIndex = 0; annotationIndex < annotationsSize; annotationIndex++) {
        DexAnnotation annotation = info.getAnnotations().get(annotationIndex);
        visibilities[annotationIndex] = DexValueByte.create((byte) annotation.getVisibility());
        annotations[annotationIndex] = new DexValueAnnotation(annotation.annotation);
      }
    }

    return new DexAnnotation(
        VISIBILITY_SYSTEM,
        new DexEncodedAnnotation(
            factory.annotationRecord,
            new DexAnnotationElement[] {
              new DexAnnotationElement(
                  factory.annotationRecordComponentNames, new DexValueArray(componentNames)),
              new DexAnnotationElement(
                  factory.annotationRecordComponentTypes, new DexValueArray(componentTypes)),
              new DexAnnotationElement(
                  factory.annotationRecordComponentSignatures,
                  new DexValueArray(componentSignatures)),
              new DexAnnotationElement(
                  factory.annotationRecordComponentAnnotationVisibilities,
                  new DexValueArray(componentAnnotationVisibilities)),
              new DexAnnotationElement(
                  factory.annotationRecordComponentAnnotations,
                  new DexValueArray(componentAnnotations))
            }));
  }

  public static String getSignature(DexAnnotation signatureAnnotation) {
    return getSignature(signatureAnnotation.annotation);
  }

  public static String getSignature(DexEncodedAnnotation signatureAnnotation) {
    return getSignature(signatureAnnotation.elements[0].value.asDexValueArray());
  }

  public static String getSignature(DexValueArray elements) {
    StringBuilder signature = new StringBuilder();
    for (DexValue element : elements.getValues()) {
      signature.append(element.asDexValueString().value.toString());
    }
    return signature.toString();
  }

  public static String getSignature(DexAnnotationSet signatureAnnotations, DexItemFactory factory) {
    DexAnnotation signature = signatureAnnotations.getFirstMatching(factory.annotationSignature);
    return signature == null ? null : getSignature(signature);
  }

  public static DexAnnotation createThrowsAnnotation(DexValue[] exceptions,
      DexItemFactory factory) {
    return createSystemValueAnnotation(factory.annotationThrows, factory,
        new DexValueArray(exceptions));
  }

  private static DexAnnotation createSystemValueAnnotation(DexType type, DexItemFactory factory,
      DexValue value) {
    return new DexAnnotation(VISIBILITY_SYSTEM,
        new DexEncodedAnnotation(type, new DexAnnotationElement[]{
            new DexAnnotationElement(factory.createString("value"), value)
        }));
  }

  @SuppressWarnings("ReferenceEquality")
  private static DexValue getSystemValueAnnotationValue(DexType type, DexAnnotation annotation) {
    assert annotation.visibility == VISIBILITY_SYSTEM;
    assert annotation.annotation.type == type;
    return annotation.annotation.elements.length == 0
        ? null
        : annotation.annotation.elements[0].value;
  }

  @SuppressWarnings("ReferenceEquality")
  private static DexValue getSystemValueAnnotationValueWithName(
      DexType type, DexAnnotation annotation, DexString name) {
    assert annotation.visibility == VISIBILITY_SYSTEM;
    assert annotation.getAnnotationType() == type;
    for (DexAnnotationElement element : annotation.annotation.elements) {
      if (element.name == name) {
        return element.value;
      }
    }
    return null;
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isThrowingAnnotation(DexAnnotation annotation, DexItemFactory factory) {
    return annotation.annotation.type == factory.annotationThrows;
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isSignatureAnnotation(DexAnnotation annotation, DexItemFactory factory) {
    return annotation.annotation.type == factory.annotationSignature;

  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isAnnotationDefaultAnnotation(
      DexAnnotation annotation, DexItemFactory factory) {
    return annotation.annotation.type == factory.annotationDefault;
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isJavaLangRetentionAnnotation(
      DexAnnotation annotation, DexItemFactory factory) {
    return annotation.getAnnotationType() == factory.retentionType;
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isSourceDebugExtension(DexAnnotation annotation, DexItemFactory factory) {
    return annotation.annotation.type == factory.annotationSourceDebugExtension;
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isParameterNameAnnotation(
      DexAnnotation annotation, DexItemFactory factory) {
    return annotation.annotation.type == factory.annotationMethodParameters;
  }

  /**
   * As a simple heuristic for compressing a signature by splitting on fully qualified class names
   * and make them individual part. All other parts of the signature are simply grouped and separate
   * the names.
   * For examples, "()Ljava/lang/List<Lfoo/bar/Baz;>;" splits into:
   * <pre>
   *   ["()", "Ljava/lang/List<", "Lfoo/bar/Baz;", ">;"]
   * </pre>
   */
  private static DexValue compressSignature(String signature, DexItemFactory factory) {
    final int length = signature.length();
    List<DexValue> parts = new ArrayList<>();

    for (int at = 0; at < length; /*at*/) {
      char c = signature.charAt(at);
      int endAt = at + 1;
      if (c == 'L') {
        // Scan to ';' or '<' and consume them.
        while (endAt < length) {
          c = signature.charAt(endAt);
          if (c == ';' || c == '<') {
            endAt++;
            break;
          }
          endAt++;
        }
      } else {
        // Scan to 'L' without consuming it.
        while (endAt < length) {
          c = signature.charAt(endAt);
          if (c == 'L') {
            break;
          }
          endAt++;
        }
      }

      parts.add(toDexValue(signature.substring(at, endAt), factory));
      at = endAt;
    }

    return new DexValueArray(parts.toArray(DexValue.EMPTY_ARRAY));
  }

  private static DexValue toDexValue(String string, DexItemFactory factory) {
    return new DexValueString(factory.createString(string));
  }

  public static DexAnnotation createAnnotationSynthesizedClass(
      SyntheticKind kind, DexItemFactory dexItemFactory, ComputedApiLevel computedApiLevel) {
    DexString versionHash =
        dexItemFactory.createString(dexItemFactory.getSyntheticNaming().getVersionHash());
    DexAnnotationElement kindElement =
        new DexAnnotationElement(dexItemFactory.kindString, DexValueInt.create(kind.getId()));
    DexAnnotationElement versionHashElement =
        new DexAnnotationElement(dexItemFactory.versionHashString, new DexValueString(versionHash));
    int apiLevel = getApiLevelForSerialization(computedApiLevel);
    DexAnnotationElement apiLevelElement =
        new DexAnnotationElement(dexItemFactory.apiLevelString, DexValueInt.create(apiLevel));
    DexAnnotationElement[] elements =
        new DexAnnotationElement[] {apiLevelElement, kindElement, versionHashElement};
    return new DexAnnotation(
        VISIBILITY_BUILD,
        new DexEncodedAnnotation(dexItemFactory.annotationSynthesizedClass, elements));
  }

  public static boolean hasSynthesizedClassAnnotation(
      DexAnnotationSet annotations,
      DexItemFactory factory,
      SyntheticItems synthetics,
      AndroidApiLevelCompute apiLevelCompute) {
    return getSynthesizedClassAnnotationInfo(annotations, factory, synthetics, apiLevelCompute)
        != null;
  }

  @SuppressWarnings("ReferenceEquality")
  public static SynthesizedAnnotationClassInfo getSynthesizedClassAnnotationInfo(
      DexAnnotationSet annotations,
      DexItemFactory factory,
      SyntheticItems synthetics,
      AndroidApiLevelCompute apiLevelCompute) {
    if (annotations.size() != 1) {
      return null;
    }
    DexAnnotation annotation = annotations.annotations[0];
    if (annotation.annotation.type != factory.annotationSynthesizedClass) {
      return null;
    }
    int length = annotation.annotation.elements.length;
    if (length != 3) {
      return null;
    }
    assert factory.kindString.isLessThan(factory.versionHashString);
    DexAnnotationElement apiLevelElement = annotation.annotation.elements[0];
    DexAnnotationElement kindElement = annotation.annotation.elements[1];
    DexAnnotationElement versionHashElement = annotation.annotation.elements[2];
    if (kindElement.name != factory.kindString) {
      return null;
    }
    if (!kindElement.value.isDexValueInt()) {
      return null;
    }
    if (versionHashElement.name != factory.versionHashString) {
      return null;
    }
    if (!versionHashElement.value.isDexValueString()) {
      return null;
    }
    if (apiLevelElement.name != factory.apiLevelString || !apiLevelElement.value.isDexValueInt()) {
      return null;
    }
    String currentVersionHash = synthetics.getNaming().getVersionHash();
    String syntheticVersionHash = versionHashElement.value.asDexValueString().getValue().toString();
    if (!currentVersionHash.equals(syntheticVersionHash)) {
      return null;
    }
    int apiLevelValue = apiLevelElement.value.asDexValueInt().getValue();
    ComputedApiLevel computedApiLevel = getSerializedApiLevel(apiLevelCompute, apiLevelValue);
    SyntheticKind syntheticKind =
        synthetics.getNaming().fromId(kindElement.value.asDexValueInt().getValue());
    assert syntheticKind != synthetics.getNaming().API_MODEL_OUTLINE
        || computedApiLevel.isKnownApiLevel();
    return SynthesizedAnnotationClassInfo.create(syntheticKind, computedApiLevel);
  }

  private static int getApiLevelForSerialization(ComputedApiLevel computedApiLevel) {
    if (computedApiLevel.isNotSetApiLevel()) {
      return NOT_SET_API_LEVEL;
    } else if (computedApiLevel.isUnknownApiLevel()) {
      return UNKNOWN_API_LEVEL;
    } else {
      assert computedApiLevel.isKnownApiLevel();
      return computedApiLevel.asKnownApiLevel().getApiLevel().getLevel();
    }
  }

  private static ComputedApiLevel getSerializedApiLevel(
      AndroidApiLevelCompute apiLevelCompute, int apiLevelValue) {
    if (apiLevelValue == NOT_SET_API_LEVEL) {
      return ComputedApiLevel.notSet();
    } else if (apiLevelValue == UNKNOWN_API_LEVEL) {
      return ComputedApiLevel.unknown();
    } else {
      return apiLevelCompute.of(AndroidApiLevel.getAndroidApiLevel(apiLevelValue));
    }
  }

  @SuppressWarnings("ReferenceEquality")
  public DexAnnotation rewrite(Function<DexEncodedAnnotation, DexEncodedAnnotation> rewriter) {
    DexEncodedAnnotation rewritten = rewriter.apply(annotation);
    if (rewritten == annotation) {
      return this;
    }
    if (rewritten == null) {
      return null;
    }
    return new DexAnnotation(visibility, rewritten);
  }

  public static class SynthesizedAnnotationClassInfo {

    private final SyntheticKind syntheticKind;
    private final ComputedApiLevel computedApiLevel;

    private SynthesizedAnnotationClassInfo(
        SyntheticKind syntheticKind, ComputedApiLevel computedApiLevel) {
      this.syntheticKind = syntheticKind;
      this.computedApiLevel = computedApiLevel;
    }

    private static SynthesizedAnnotationClassInfo create(
        SyntheticKind syntheticKind, ComputedApiLevel computedApiLevel) {
      return new SynthesizedAnnotationClassInfo(syntheticKind, computedApiLevel);
    }

    public SyntheticKind getSyntheticKind() {
      return syntheticKind;
    }

    public ComputedApiLevel getComputedApiLevel() {
      return computedApiLevel;
    }
  }
}
