/*
 * Copyright 2019 The Bazel Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.devtools.build.android.desugar.langmodel;

import static com.google.common.base.Preconditions.checkState;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import org.objectweb.asm.Type;

/** The key to index a class or interface method or constructor. */
@AutoValue
public abstract class MethodKey extends ClassMemberKey<MethodKey> {

  /** The factory method for {@link MethodKey}. */
  public static MethodKey create(ClassName ownerClass, String name, String descriptor) {
    checkState(
        descriptor.isEmpty() // Allows empty descriptor for non-overloaded methods.
            || descriptor.startsWith("("),
        "Expected a method descriptor. Actual: (%s#%s:%s)",
        ownerClass,
        name,
        descriptor);
    return new AutoValue_MethodKey(ownerClass, name, descriptor);
  }

  /** The return type of a method. */
  public Type getReturnType() {
    return Type.getReturnType(descriptor());
  }

  /** The return type of a method. */
  public ClassName getReturnTypeName() {
    return ClassName.create(Type.getReturnType(descriptor()));
  }

  /** The formal parameter types of a method. */
  public Type[] getArgumentTypeArray() {
    return Type.getArgumentTypes(descriptor());
  }

  /** The formal parameter types of a method. */
  public ImmutableList<Type> getArgumentTypes() {
    return ImmutableList.copyOf(getArgumentTypeArray());
  }

  /** The synthetic constructor for a private constructor. */
  public final MethodKey bridgeOfConstructor(ClassName nestCompanion) {
    checkState(isConstructor(), "Expect to use for a constructor but is %s", this);
    Type companionClassType = nestCompanion.toAsmObjectType();
    ImmutableList<Type> argumentTypes = getArgumentTypes();
    ImmutableList<Type> bridgeConstructorArgTypes =
        ImmutableList.<Type>builder().addAll(argumentTypes).add(companionClassType).build();
    return create(
        owner(),
        name(),
        Type.getMethodDescriptor(getReturnType(), bridgeConstructorArgTypes.toArray(new Type[0])));
  }

  /** The synthetic bridge method for a private static method in a class. */
  public final MethodKey bridgeOfClassStaticMethod() {
    checkState(!isConstructor(), "Expect a non-constructor method but is a constructor %s", this);
    return create(owner(), nameWithSuffix("bridge"), descriptor());
  }

  /** The synthetic bridge method for a private instance method in a class. */
  public final MethodKey bridgeOfClassInstanceMethod() {
    return create(owner(), nameWithSuffix("bridge"), instanceMethodToStaticDescriptor(this));
  }

  /** The substitute method for a private static method in an interface. */
  public final MethodKey substituteOfInterfaceStaticMethod() {
    checkState(!isConstructor(), "Expect a non-constructor: %s", this);
    return create(owner(), name(), descriptor());
  }

  /** The substitute method for a private instance method in an interface. */
  public final MethodKey substituteOfInterfaceInstanceMethod() {
    return create(owner(), name(), instanceMethodToStaticDescriptor(this));
  }

  /** The descriptor of the static version of a given instance method. */
  private static String instanceMethodToStaticDescriptor(MethodKey methodKey) {
    checkState(!methodKey.isConstructor(), "Expect a Non-constructor method: %s", methodKey);
    ImmutableList<Type> argumentTypes = methodKey.getArgumentTypes();
    ImmutableList<Type> bridgeMethodArgTypes =
        ImmutableList.<Type>builder()
            .add(methodKey.ownerAsmObjectType())
            .addAll(argumentTypes)
            .build();
    return Type.getMethodDescriptor(
        methodKey.getReturnType(), bridgeMethodArgTypes.toArray(new Type[0]));
  }

  @Override
  public MethodKey acceptTypeMapper(TypeMapper typeMapper) {
    return MethodKey.create(typeMapper.map(owner()), name(), typeMapper.mapDesc(descriptor()));
  }

  /**
   * Accepts a {@link MethodInstrVisitor} that visits all kinds of method invocation instructions.
   */
  public final <R, P> R accept(
      MemberUseKind methodInstrOpcode,
      boolean isInterface,
      MethodInstrVisitor<R, ? super MethodKey, P> visitor,
      P param) {
    if (isConstructor()) {
      checkState(methodInstrOpcode == MemberUseKind.INVOKESPECIAL);
      return visitor.visitConstructorInvokeSpecial(this, param);
    } else if (isInterface) {
      switch (methodInstrOpcode) {
        case INVOKESPECIAL:
          // Super call to an non-abstract instance interface method.
          return visitor.visitInterfaceInvokeSpecial(this, param);
        case INVOKESTATIC:
          return visitor.visitInterfaceInvokeStatic(this, param);
        case INVOKEINTERFACE:
          return visitor.visitInvokeInterface(this, param);
        default:
          throw new AssertionError(
              String.format(
                  "Unexpected Opcode: (%s) invoked on Interface Method(%s).\n"
                      + "Opcode Reference: {INVOKEVIRTUAL(182), INVOKESPECIAL(183),"
                      + " INVOKESTATIC(184), INVOKEINTERFACE(185), INVOKEDYNAMIC(186)}",
                  methodInstrOpcode, this));
      }
    } else {
      switch (methodInstrOpcode) {
        case INVOKEVIRTUAL:
          return visitor.visitInvokeVirtual(this, param);
        case INVOKESPECIAL:
          return visitor.visitInvokeSpecial(this, param);
        case INVOKESTATIC:
          return visitor.visitInvokeStatic(this, param);
        case INVOKEDYNAMIC:
          return visitor.visitInvokeDynamic(this, param);
        default:
          throw new AssertionError(
              String.format(
                  "Unexpected Opcode: (%s) invoked on class Method(%s).\n"
                      + "Opcode Reference: {INVOKEVIRTUAL(182), INVOKESPECIAL(183),"
                      + " INVOKESTATIC(184), INVOKEINTERFACE(185), INVOKEDYNAMIC(186)}",
                  methodInstrOpcode, this));
      }
    }
  }
}
