// Copyright (c) 2017, 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.Constants;
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.code.InvokeType;
import com.android.tools.r8.lightir.LirConstant;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.structural.CompareToVisitor;
import com.android.tools.r8.utils.structural.HashingVisitor;
import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import java.util.Objects;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;

public class DexMethodHandle extends IndexedDexItem
    implements NamingLensComparable<DexMethodHandle>, LirConstant {

  @Override
  public LirConstantOrder getLirConstantOrder() {
    return LirConstantOrder.METHOD_HANDLE;
  }

  @Override
  public int internalLirConstantAcceptCompareTo(LirConstant other, CompareToVisitor visitor) {
    return acceptCompareTo((DexMethodHandle) other, visitor);
  }

  @Override
  public void internalLirConstantAcceptHashing(HashingVisitor visitor) {
    acceptHashing(visitor);
  }

  public enum MethodHandleType {
    STATIC_PUT((short) 0x00),
    STATIC_GET((short) 0x01),
    INSTANCE_PUT((short) 0x02),
    INSTANCE_GET((short) 0x03),
    INVOKE_STATIC((short) 0x04),
    INVOKE_INSTANCE((short) 0x05),
    INVOKE_CONSTRUCTOR((short) 0x06),
    INVOKE_DIRECT((short) 0x07),
    INVOKE_INTERFACE((short) 0x08),
    // Internal method handle needed by lambda desugaring.
    // TODO(b/200254463): Remove this now that lambda desugaring is CF/CF.
    INVOKE_SUPER((short) 0x09);

    private final short value;

    MethodHandleType(short value) {
      this.value = value;
    }

    public short getValue() {
      return value;
    }

    public static MethodHandleType getKind(int value) {
      MethodHandleType kind;

      switch (value) {
        case 0x00:
          kind = STATIC_PUT;
          break;
        case 0x01:
          kind = STATIC_GET;
          break;
        case 0x02:
          kind = INSTANCE_PUT;
          break;
        case 0x03:
          kind = INSTANCE_GET;
          break;
        case 0x04:
          kind = INVOKE_STATIC;
          break;
        case 0x05:
          kind = INVOKE_INSTANCE;
          break;
        case 0x06:
          kind = INVOKE_CONSTRUCTOR;
          break;
        case 0x07:
          kind = INVOKE_DIRECT;
          break;
        case 0x08:
          kind = INVOKE_INTERFACE;
          break;
        case 0x09:
          kind = INVOKE_SUPER;
          break;
        default:
          throw new AssertionError();
      }

      assert kind.getValue() == value;
      return kind;
    }

    @SuppressWarnings("ReferenceEquality")
    public static MethodHandleType fromAsmHandle(
        Handle handle, JarApplicationReader application, DexType clazz) {
      switch (handle.getTag()) {
        case Opcodes.H_GETFIELD:
          return MethodHandleType.INSTANCE_GET;
        case Opcodes.H_GETSTATIC:
          return MethodHandleType.STATIC_GET;
        case Opcodes.H_PUTFIELD:
          return MethodHandleType.INSTANCE_PUT;
        case Opcodes.H_PUTSTATIC:
          return MethodHandleType.STATIC_PUT;
        case Opcodes.H_INVOKESPECIAL:
          assert !handle.getName().equals(Constants.INSTANCE_INITIALIZER_NAME);
          assert !handle.getName().equals(Constants.CLASS_INITIALIZER_NAME);
          DexType owner = application.getTypeFromName(handle.getOwner());
          if (owner == clazz) {
            return MethodHandleType.INVOKE_DIRECT;
          } else {
            return MethodHandleType.INVOKE_SUPER;
          }
        case Opcodes.H_INVOKEVIRTUAL:
          return MethodHandleType.INVOKE_INSTANCE;
        case Opcodes.H_INVOKEINTERFACE:
          return MethodHandleType.INVOKE_INTERFACE;
        case Opcodes.H_INVOKESTATIC:
          return MethodHandleType.INVOKE_STATIC;
        case Opcodes.H_NEWINVOKESPECIAL:
          return MethodHandleType.INVOKE_CONSTRUCTOR;
        default:
          throw new Unreachable("MethodHandle tag is not supported: " + handle.getTag());
      }
    }

    public boolean isFieldType() {
      return isStaticPut() || isStaticGet() || isInstancePut() || isInstanceGet();
    }

    public boolean isMethodType() {
      return isInvokeStatic() || isInvokeInstance() || isInvokeInterface() || isInvokeSuper()
          || isInvokeConstructor() || isInvokeDirect();
    }

    public boolean isStaticPut() {
      return this == MethodHandleType.STATIC_PUT;
    }

    public boolean isStaticGet() {
      return this == MethodHandleType.STATIC_GET;
    }

    public boolean isInstancePut() {
      return this == MethodHandleType.INSTANCE_PUT;
    }

    public boolean isInstanceGet() {
      return this == MethodHandleType.INSTANCE_GET;
    }

    public boolean isInvokeStatic() {
      return this == MethodHandleType.INVOKE_STATIC;
    }

    public boolean isInvokeDirect() {
      return this == MethodHandleType.INVOKE_DIRECT;
    }

    public boolean isInvokeInstance() {
      return this == MethodHandleType.INVOKE_INSTANCE;
    }

    public boolean isInvokeInterface() {
      return this == MethodHandleType.INVOKE_INTERFACE;
    }

    public boolean isInvokeSuper() {
      return this == MethodHandleType.INVOKE_SUPER;
    }

    public boolean isInvokeConstructor() {
      return this == MethodHandleType.INVOKE_CONSTRUCTOR;
    }

    public InvokeType toInvokeType() {
      assert isMethodType();
      switch (this) {
        case INVOKE_STATIC:
          return InvokeType.STATIC;
        case INVOKE_INSTANCE:
          return InvokeType.VIRTUAL;
        case INVOKE_CONSTRUCTOR:
          return InvokeType.DIRECT;
        case INVOKE_DIRECT:
          return InvokeType.DIRECT;
        case INVOKE_INTERFACE:
          return InvokeType.INTERFACE;
        case INVOKE_SUPER:
          return InvokeType.SUPER;
        default:
          throw new Unreachable(
              "Conversion to invoke type with unexpected method handle: " + this);
      }
    }
  }

  public final MethodHandleType type;

  // Field or method that the method handle is targeting.
  public final DexMember<? extends DexItem, ? extends DexMember<?, ?>> member;

  public final boolean isInterface;

  // If the method handle is of method type and is not an argument to a lambda metafactory
  // the method handle could flow to an invokeExact instruction which does equality checking
  // on method descriptors including the receiver. Therefore, for such method handles we
  // cannot perform rewriting of the receiver as that will make the invokeExact invocation
  // fail due to type mismatch. Therefore, fieldOrMethod will contain the method handle
  // as we want it in the output with the original receiver. That means that member rebinding
  // has not been applied to fieldOrMethod. Since renaming happens on member rebound dex methods
  // we need to record the member rebound target as well for naming. That is what rewrittenTarget
  // is for.
  public final DexMethod rewrittenTarget;

  public DexMethodHandle(
      MethodHandleType type,
      DexMember<? extends DexItem, ? extends DexMember<?, ?>> member,
      boolean isInterface,
      DexMethod rewrittenTarget) {
    this.type = type;
    this.member = member;
    this.isInterface = isInterface;
    this.rewrittenTarget = rewrittenTarget;
  }

  public static DexMethodHandle fromAsmHandle(
      Handle handle, JarApplicationReader application, DexType clazz) {
    MethodHandleType methodHandleType = MethodHandleType.fromAsmHandle(handle, application, clazz);
    DexMember<? extends DexItem, ? extends DexMember<?, ?>> descriptor =
        methodHandleType.isFieldType()
            ? application.getField(handle.getOwner(), handle.getName(), handle.getDesc())
            : application.getMethod(handle.getOwner(), handle.getName(), handle.getDesc());
    return application.getMethodHandle(methodHandleType, descriptor, handle.isInterface());
  }

  @Override
  public int computeHashCode() {
    return Objects.hash(type, member.computeHashCode(), isInterface, rewrittenTarget);
  }

  @Override
  public boolean computeEquals(Object other) {
    if (other instanceof DexMethodHandle) {
      DexMethodHandle o = (DexMethodHandle) other;
      return type.equals(o.type)
          && member.equals(o.member)
          && (isInterface == o.isInterface)
          && Objects.equals(rewrittenTarget, o.rewrittenTarget);
    }
    return false;
  }

  @Override
  public String toString() {
    StringBuilder builder =
        new StringBuilder("MethodHandle: {")
            .append(type)
            .append(", ")
            .append(member.toSourceString())
            .append("}");
    return builder.toString();
  }

  public void collectIndexedItems(AppView<?> appView, IndexedItemCollection indexedItems) {
    if (indexedItems.addMethodHandle(this)) {
      if (member.isDexField()) {
        DexField field = member.asDexField();
        field.collectIndexedItems(appView, indexedItems);
      } else {
        DexMethod method = member.asDexMethod();
        if (rewrittenTarget != null) {
          // If there is a rewritten target we need to use that to get the right name of the
          // targeted method (only member rebound methods take part in naming). The rest of the
          // indexed items are collected from method.
          if (method.collectIndexedItemsExceptName(appView, indexedItems)) {
            rewrittenTarget.collectIndexedItemsName(appView, indexedItems);
          }
        } else {
          method.collectIndexedItems(appView, indexedItems);
        }
      }
    }
  }

  @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 boolean isFieldHandle() {
    return type.isFieldType();
  }

  public boolean isMethodHandle() {
    return type.isMethodType();
  }

  public boolean isStaticHandle() {
    return type.isStaticPut() || type.isStaticGet() || type.isInvokeStatic();
  }

  public DexMethod asMethod() {
    assert isMethodHandle();
    return (DexMethod) member;
  }

  public DexField asField() {
    assert isFieldHandle();
    return (DexField) member;
  }

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

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

  private static void specify(StructuralSpecification<DexMethodHandle, ?> spec) {
    spec.withInt(m -> m.type.getValue())
        .withConditionalItem(DexMethodHandle::isFieldHandle, DexMethodHandle::asField)
        .withConditionalItem(DexMethodHandle::isMethodHandle, DexMethodHandle::asMethod)
        .withBool(m -> m.isInterface)
        .withNullableItem(m -> m.rewrittenTarget);
  }

  public Handle toAsmHandle(NamingLens lens) {
    String owner;
    String name;
    String desc;
    boolean itf;
    if (isMethodHandle()) {
      DexMethod method = asMethod();
      owner = lens.lookupInternalName(method.holder);
      name =
          rewrittenTarget != null
              ? lens.lookupName(rewrittenTarget).toString()
              : lens.lookupName(method).toString();
      desc = method.proto.toDescriptorString(lens);
      if (method.holder.toDescriptorString().equals("Ljava/lang/invoke/LambdaMetafactory;")) {
        assert !isInterface;
        itf = false;
      } else {
        itf = isInterface;
      }
    } else {
      assert isFieldHandle();
      DexField field = asField();
      owner = lens.lookupInternalName(field.holder);
      name = lens.lookupName(field).toString();
      desc = lens.lookupDescriptor(field.type).toString();
      itf = isInterface;
    }
    return new Handle(getAsmTag(), owner, name, desc, itf);
  }

  private int getAsmTag() {
    switch (type) {
      case INVOKE_STATIC:
        return Opcodes.H_INVOKESTATIC;
      case INVOKE_CONSTRUCTOR:
        return Opcodes.H_NEWINVOKESPECIAL;
      case INVOKE_INSTANCE:
        return Opcodes.H_INVOKEVIRTUAL;
      case INVOKE_SUPER:
      case INVOKE_DIRECT:
        return Opcodes.H_INVOKESPECIAL;
      case STATIC_GET:
        return Opcodes.H_GETSTATIC;
      case STATIC_PUT:
        return Opcodes.H_PUTSTATIC;
      case INSTANCE_GET:
        return Opcodes.H_GETFIELD;
      case INSTANCE_PUT:
        return Opcodes.H_PUTFIELD;
      case INVOKE_INTERFACE:
        return Opcodes.H_INVOKEINTERFACE;
      default:
        throw new Unreachable();
    }
  }
}
