// 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.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import java.nio.charset.StandardCharsets;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;

public class SyntheticMarker {

  private static final String SYNTHETIC_MARKER_ATTRIBUTE_TYPE_NAME =
      "com.android.tools.r8.SynthesizedClassV2";

  public static Attribute getMarkerAttributePrototype(SyntheticNaming syntheticNaming) {
    return new MarkerAttribute(null, null, syntheticNaming);
  }

  public static void writeMarkerAttribute(
      ClassWriter writer, SyntheticKind kind, SyntheticItems syntheticItems) {
    SyntheticNaming naming = syntheticItems.getNaming();
    writer.visitAttribute(new MarkerAttribute(kind, naming.getVersionHash(), naming));
  }

  public static SyntheticMarker readMarkerAttribute(Attribute attribute) {
    if (attribute instanceof MarkerAttribute) {
      MarkerAttribute marker = (MarkerAttribute) attribute;
      if (marker.versionHash.equals(marker.syntheticNaming.getVersionHash())) {
        return new SyntheticMarker(marker.kind, null);
      }
    }
    return null;
  }

  /**
   * CF attribute for marking synthetic classes.
   *
   * <p>The attribute name is defined by {@code SYNTHETIC_MARKER_ATTRIBUTE_TYPE_NAME}. The format of
   * the attribute payload is
   *
   * <pre>
   *   u2 syntheticKindId
   *   u2 versionHashLength
   *   u1[versionHashLength] versionHashBytes
   * </pre>
   */
  private static class MarkerAttribute extends Attribute {

    private final SyntheticKind kind;
    private final String versionHash;
    private final SyntheticNaming syntheticNaming;

    public MarkerAttribute(
        SyntheticKind kind, String versionHash, SyntheticNaming syntheticNaming) {
      super(SYNTHETIC_MARKER_ATTRIBUTE_TYPE_NAME);
      this.kind = kind;
      this.versionHash = versionHash;
      this.syntheticNaming = syntheticNaming;
    }

    @Override
    protected Attribute read(
        ClassReader classReader,
        int offset,
        int length,
        char[] charBuffer,
        int codeAttributeOffset,
        Label[] labels) {
      short syntheticKindId = classReader.readShort(offset);
      offset += 2;
      short versionHashLength = classReader.readShort(offset);
      offset += 2;
      byte[] versionHashBytes = new byte[versionHashLength];
      for (int i = 0; i < versionHashLength; i++) {
        versionHashBytes[i] = (byte) classReader.readByte(offset++);
      }
      assert syntheticKindId >= 0;
      SyntheticKind kind = syntheticNaming.fromId(syntheticKindId);
      String versionHash = new String(versionHashBytes, StandardCharsets.UTF_8);
      return new MarkerAttribute(kind, versionHash, syntheticNaming);
    }

    @Override
    protected ByteVector write(
        ClassWriter classWriter, byte[] code, int codeLength, int maxStack, int maxLocals) {
      assert 0 <= kind.getId() && kind.getId() <= Short.MAX_VALUE;
      ByteVector byteVector = new ByteVector();
      byteVector.putShort(kind.getId());
      byte[] versionHashBytes = versionHash.getBytes(StandardCharsets.UTF_8);
      byteVector.putShort(versionHashBytes.length);
      byteVector.putByteArray(versionHashBytes, 0, versionHashBytes.length);
      return byteVector;
    }
  }

  public static void addMarkerToClass(
      DexProgramClass clazz, SyntheticKind kind, InternalOptions options) {
    // TODO(b/158159959): Consider moving this to the dex writer similar to the CF case.
    assert !options.isGeneratingClassFiles();
    clazz.setAnnotations(
        clazz
            .annotations()
            .getWithAddedOrReplaced(
                DexAnnotation.createAnnotationSynthesizedClass(kind, options.itemFactory)));
  }

  public static SyntheticMarker stripMarkerFromClass(DexProgramClass clazz, AppView<?> appView) {
    if (clazz.originatesFromClassResource()) {
      SyntheticMarker marker = clazz.stripSyntheticInputMarker();
      if (marker == null) {
        return NO_MARKER;
      }
      assert marker.getContext() == null;
      DexType contextType =
          getSyntheticContextType(clazz.type, marker.kind, appView.dexItemFactory());
      SynthesizingContext context =
          SynthesizingContext.fromSyntheticInputClass(clazz, contextType, appView);
      return new SyntheticMarker(marker.kind, context);
    }
    SyntheticMarker marker = internalStripMarkerFromClass(clazz, appView);
    assert marker != NO_MARKER
        || !DexAnnotation.hasSynthesizedClassAnnotation(
            clazz.annotations(), appView.dexItemFactory(), appView.getSyntheticItems());
    return marker;
  }

  private static SyntheticMarker internalStripMarkerFromClass(
      DexProgramClass clazz, AppView<?> appView) {
    if (clazz.superType != appView.dexItemFactory().objectType) {
      return NO_MARKER;
    }
    if (isDefinitelyNotSyntheticProgramClass(clazz)) {
      return NO_MARKER;
    }
    SyntheticKind kind =
        DexAnnotation.getSynthesizedClassAnnotationInfo(
            clazz.annotations(), appView.dexItemFactory(), appView.getSyntheticItems());
    if (kind == null) {
      return NO_MARKER;
    }
    assert clazz.annotations().size() == 1;
    if (kind.isSingleSyntheticMethod()) {
      if (!clazz.interfaces.isEmpty()) {
        return NO_MARKER;
      }
      for (DexEncodedMethod method : clazz.methods()) {
        if (!SyntheticMethodBuilder.isValidSingleSyntheticMethod(method)) {
          return NO_MARKER;
        }
      }
    }
    clazz.setAnnotations(DexAnnotationSet.empty());
    DexType context = getSyntheticContextType(clazz.type, kind, appView.dexItemFactory());
    return new SyntheticMarker(
        kind, SynthesizingContext.fromSyntheticInputClass(clazz, context, appView));
  }

  // Filters out definitely not synthetic classes to avoid expensive computations on all classes.
  public static boolean isDefinitelyNotSyntheticProgramClass(DexProgramClass clazz) {
    ClassAccessFlags flags = clazz.accessFlags;
    return !flags.isSynthetic() || flags.isEnum();
  }

  private static DexType getSyntheticContextType(
      DexType type, SyntheticKind kind, DexItemFactory factory) {
    if (kind.isGlobal()) {
      return type;
    }
    String prefix = SyntheticNaming.getPrefixForExternalSyntheticType(kind, type);
    return factory.createType(DescriptorUtils.getDescriptorFromClassBinaryName(prefix));
  }

  private static final SyntheticMarker NO_MARKER = new SyntheticMarker(null, null);

  private final SyntheticKind kind;
  private final SynthesizingContext context;

  public SyntheticMarker(SyntheticKind kind, SynthesizingContext context) {
    this.kind = kind;
    this.context = context;
  }

  public boolean isSyntheticMethods() {
    return kind != null && kind.isSingleSyntheticMethod();
  }

  public boolean isSyntheticClass() {
    return kind != null && !kind.isSingleSyntheticMethod();
  }

  public SyntheticKind getKind() {
    return kind;
  }

  public SynthesizingContext getContext() {
    return context;
  }
}
