// 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.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
import com.android.tools.r8.graph.DexValue.DexValueMethodType;
import com.android.tools.r8.graph.DexValue.DexValueString;
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 com.google.common.io.BaseEncoding;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.InvokeDynamicInsnNode;

public final class DexCallSite extends IndexedDexItem implements StructuralItem<DexCallSite> {

  public final DexString methodName;
  public final DexProto methodProto;

  public final DexMethodHandle bootstrapMethod;
  public final List<DexValue> bootstrapArgs;

  // Lazy computed encoding derived from the above immutable fields.
  private DexEncodedArray encodedArray = null;

  // Only used for sorting for deterministic output. This is the method and the instruction
  // offset where this DexCallSite ends up in the output.
  private DexMethod method;
  private int instructionOffset = -1;

  private static void specify(StructuralSpecification<DexCallSite, ?> spec) {
    spec
        // Use the possibly absent "context" info as the major key for sorting.
        // TODO(b/171867022): Investigate if this is needed now that a call-site can be sorted based
        //  on its content directly.
        .withNullableItem(c -> c.method)
        .withInt(c -> c.instructionOffset)
        // Actual call-site content.
        .withItem(c -> c.methodName)
        .withItem(c -> c.methodProto)
        .withItem(c -> c.bootstrapMethod)
        .withItemCollection(c -> c.bootstrapArgs);
  }

  DexCallSite(
      DexString methodName,
      DexProto methodProto,
      DexMethodHandle bootstrapMethod,
      List<DexValue> bootstrapArgs) {
    assert methodName != null;
    assert methodProto != null;
    assert bootstrapMethod != null;
    assert bootstrapArgs != null;

    this.methodName = methodName;
    this.methodProto = methodProto;
    this.bootstrapMethod = bootstrapMethod;
    this.bootstrapArgs = bootstrapArgs;
  }

  public static DexCallSite fromAsmInvokeDynamic(
      InvokeDynamicInsnNode insn, JarApplicationReader application, DexType clazz) {
    return fromAsmInvokeDynamic(application, clazz, insn.name, insn.desc, insn.bsm, insn.bsmArgs);
  }

  public static DexCallSite fromAsmInvokeDynamic(
      JarApplicationReader application,
      DexType clazz,
      String name,
      String desc,
      Handle bsmHandle,
      Object[] bsmArgs) {
    // Bootstrap method
    if (bsmHandle.getTag() != Opcodes.H_INVOKESTATIC
        && bsmHandle.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
      // JVM9 §4.7.23 note: Tag must be InvokeStatic or NewInvokeSpecial.
      throw new CompilationError("Bootstrap handle invalid: tag == " + bsmHandle.getTag());
    }
    // Resolve the bootstrap method.
    DexMethodHandle bootstrapMethod = DexMethodHandle.fromAsmHandle(bsmHandle, application, clazz);

    // Decode static bootstrap arguments
    List<DexValue> bootstrapArgs = new ArrayList<>();
    for (Object arg : bsmArgs) {
      bootstrapArgs.add(DexValue.fromAsmBootstrapArgument(arg, application, clazz));
    }

    // Construct call site
    return application.getCallSite(name, desc, bootstrapMethod, bootstrapArgs);
  }

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

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

  public void setContext(DexMethod method, int instructionOffset) {
    assert method != null;
    assert instructionOffset >= 0;
    assert this.method == null;
    assert this.instructionOffset == -1;
    this.method = method;
    this.instructionOffset = instructionOffset;
  }

  @Override
  public int computeHashCode() {
    // Call sites are equal only when this == other, which was already computed by the caller of
    // computeEquals. Do not share call site entries, each invoke-custom must have its own
    // call site, but the content of the entry (encoded array) in the data section can be shared.
    return System.identityHashCode(this);
  }

  @Override
  public boolean computeEquals(Object other) {
    // Call sites are equal only when this == other, which was already computed by the caller of
    // computeEquals. Do not share call site entries, each invoke-custom must have its own
    // call site, but the content of the entry (encoded array) in the data section can be shared.
    return false;
  }

  @Override
  public String toString() {
    StringBuilder builder =
        new StringBuilder("CallSite: { Name: ").append(methodName.toSourceString())
            .append(", Proto: ").append(methodProto.toSourceString())
            .append(", ").append(bootstrapMethod.toSourceString());
    String sep = ", Args: ";
    for (DexItem arg : bootstrapArgs) {
      builder.append(sep).append(arg.toSourceString());
      sep = ", ";
    }
    builder.append('}');
    return builder.toString();
  }

  public void collectIndexedItems(IndexedItemCollection indexedItems) {
    if (indexedItems.addCallSite(this)) {
      methodName.collectIndexedItems(indexedItems);
      methodProto.collectIndexedItems(indexedItems);
      bootstrapMethod.collectIndexedItems(indexedItems);
      for (DexValue arg : bootstrapArgs) {
        arg.collectIndexedItems(indexedItems);
      }
    }
  }

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

  @Override
  public int getOffset(ObjectToOffsetMapping mapping) {
    return mapping.getOffsetFor(this);
  }

  // TODO(mikaelpeltier): Adapt syntax when invoke-custom will be available into smali.
  @Override
  public String toSmaliString() {
    return toString();
  }

  public String getHash() {
    return new HashBuilder().build();
  }

  private final class HashBuilder {
    private ByteArrayOutputStream bytes;
    private ObjectOutputStream out;

    private void write(DexString string) throws IOException {
      out.writeInt(string.size); // To avoid same-prefix problem
      out.write(string.content);
    }

    private void write(DexType type) throws IOException {
      write(type.descriptor);
    }

    private void write(DexMethodHandle methodHandle) throws IOException {
      out.writeShort(methodHandle.type.getValue());
      if (methodHandle.isFieldHandle()) {
        write(methodHandle.asField());
      } else {
        write(methodHandle.asMethod());
      }
    }

    private void write(DexProto proto) throws IOException {
      write(proto.shorty);
      write(proto.returnType);
      DexType[] params = proto.parameters.values;
      out.writeInt(params.length);
      for (DexType param : params) {
        write(param);
      }
    }

    private void write(DexMethod method) throws IOException {
      write(method.holder);
      write(method.proto);
      write(method.name);
    }

    private void write(DexField field) throws IOException {
      write(field.holder);
      write(field.type);
      write(field.name);
    }

    private void write(List<DexValue> args) throws IOException {
      out.writeInt(args.size());
      for (DexValue arg : args) {
        out.writeByte(arg.getValueKind().toByte());
        switch (arg.getValueKind()) {
          case DOUBLE:
            out.writeDouble(arg.asDexValueDouble().value);
            break;
          case FLOAT:
            out.writeFloat(arg.asDexValueFloat().value);
            break;
          case INT:
            out.writeInt(arg.asDexValueInt().value);
            break;
          case LONG:
            out.writeLong(arg.asDexValueLong().value);
            break;
          case METHOD_HANDLE:
            write(arg.asDexValueMethodHandle().value);
            break;
          case METHOD_TYPE:
            write(arg.asDexValueMethodType().value);
            break;
          case STRING:
            write(arg.asDexValueString().value);
            break;
          case TYPE:
            write(arg.asDexValueType().value);
            break;
          default:
            assert false;
        }
      }
    }

    String build() {
      try {
        bytes = new ByteArrayOutputStream();
        out = new ObjectOutputStream(bytes);

        // We will generate SHA-1 hash of the call site information based on call site
        // attributes used in equality comparison, such that if the two call sites are
        // different their hashes should also be different.
        write(methodName);
        write(methodProto);
        write(bootstrapMethod);
        write(bootstrapArgs);
        out.close();

        MessageDigest digest = MessageDigest.getInstance("SHA-1");
        digest.update(bytes.toByteArray());
        return BaseEncoding.base64Url().omitPadding().encode(digest.digest());
      } catch (NoSuchAlgorithmException | IOException ex) {
        throw new Unreachable("Cannot get SHA-1 message digest");
      }
    }
  }

  public DexEncodedArray getEncodedArray() {
    if (encodedArray == null) {
      // 3 is the fixed size of the call site
      DexValue[] callSitesValues = new DexValue[3 + bootstrapArgs.size()];
      int valuesIndex = 0;
      callSitesValues[valuesIndex++] = new DexValueMethodHandle(bootstrapMethod);
      callSitesValues[valuesIndex++] = new DexValueString(methodName);
      callSitesValues[valuesIndex++] = new DexValueMethodType(methodProto);
      for (DexValue extraArgValue : bootstrapArgs) {
        callSitesValues[valuesIndex++] = extraArgValue;
      }
      encodedArray = new DexEncodedArray(callSitesValues);
    }

    return encodedArray;
  }
}
