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

import com.android.tools.r8.Keep;
import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.ImmutableList;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;

/**
 * Reference provider/factory.
 *
 * <p>The reference class provides a single point for creating and managing reference objects that
 * represent types, methods and fields in a JVM/DEX application. The objects may or may not be
 * interned/shared.
 *
 * <p>No guarantees are made on identity and all references must be compared by {@code equals}.
 */
@Keep
public final class Reference {

  public static PrimitiveReference BOOL = PrimitiveReference.BOOL;
  public static PrimitiveReference BYTE = PrimitiveReference.BYTE;
  public static PrimitiveReference CHAR = PrimitiveReference.CHAR;
  public static PrimitiveReference SHORT = PrimitiveReference.SHORT;
  public static PrimitiveReference INT = PrimitiveReference.INT;
  public static PrimitiveReference FLOAT = PrimitiveReference.FLOAT;
  public static PrimitiveReference LONG = PrimitiveReference.LONG;
  public static PrimitiveReference DOUBLE = PrimitiveReference.DOUBLE;

  private Reference() {
    // Intentionally hidden.
  }

  public static TypeReference returnTypeFromDescriptor(String descriptor) {
    return descriptor.equals("V") ? null : typeFromDescriptor(descriptor);
  }

  public static TypeReference typeFromDescriptor(String descriptor) {
    switch (descriptor.charAt(0)) {
      case 'L':
        return classFromDescriptor(descriptor);
      case '[':
        return arrayFromDescriptor(descriptor);
      default:
        return primitiveFromDescriptor(descriptor);
    }
  }

  public static TypeReference typeFromTypeName(String typeName) {
    return typeFromDescriptor(DescriptorUtils.javaTypeToDescriptor(typeName));
  }

  // Internal helper to convert Class<?> for primitive/array types too.
  private static TypeReference typeFromClass(Class<?> clazz) {
    return typeFromDescriptor(DescriptorUtils.javaTypeToDescriptor(clazz.getTypeName()));
  }

  public static PrimitiveReference primitiveFromDescriptor(String descriptor) {
    return PrimitiveReference.fromDescriptor(descriptor);
  }

  /** Get a class reference from a JVM descriptor. */
  public static ClassReference classFromDescriptor(String descriptor) {
    return ClassReference.fromDescriptor(descriptor);
  }

  /**
   * Get a class reference from a JVM binary name.
   *
   * <p>See JVM SE 9 Specification, Section 4.2.1. Binary Class and Interface Names.
   */
  public static ClassReference classFromBinaryName(String binaryName) {
    return classFromDescriptor(DescriptorUtils.getDescriptorFromClassBinaryName(binaryName));
  }

  /**
   * Get a class reference from a Java type name.
   *
   * <p>See Class.getTypeName() from Java 1.8.
   */
  public static ClassReference classFromTypeName(String typeName) {
    return classFromDescriptor(DescriptorUtils.javaTypeToDescriptor(typeName));
  }

  /** Get a class reference from a Java java.lang.Class object. */
  public static ClassReference classFromClass(Class<?> clazz) {
    return classFromTypeName(clazz.getTypeName());
  }

  /** Get an array reference from a JVM descriptor. */
  public static ArrayReference arrayFromDescriptor(String descriptor) {
    return ArrayReference.fromDescriptor(descriptor);
  }

  /** Get an array reference from a base type and dimensions. */
  public static ArrayReference array(TypeReference baseType, int dimensions) {
    return ArrayReference.fromBaseType(baseType, dimensions);
  }

  /** Get a method reference from its full reference specification. */
  public static MethodReference method(
      ClassReference holderClass,
      String methodName,
      List<TypeReference> formalTypes,
      TypeReference returnType) {
    return new MethodReference(
        holderClass, methodName, ImmutableList.copyOf(formalTypes), returnType);
  }

  /** Get a method reference from a Java reflection method. */
  public static MethodReference methodFromMethod(Method method) {
    String methodName = method.getName();
    Class<?> holderClass = method.getDeclaringClass();
    Class<?>[] parameterTypes = method.getParameterTypes();
    Class<?> returnType = method.getReturnType();
    ImmutableList.Builder<TypeReference> builder = ImmutableList.builder();
    for (Class<?> parameterType : parameterTypes) {
      builder.add(typeFromClass(parameterType));
    }
    return method(
        classFromClass(holderClass),
        methodName,
        builder.build(),
        returnType == Void.TYPE ? null : typeFromClass(returnType));
  }

  /** Get a method reference from a Java reflection constructor. */
  public static MethodReference methodFromMethod(Constructor<?> method) {
    Class<?> holderClass = method.getDeclaringClass();
    Class<?>[] parameterTypes = method.getParameterTypes();
    ImmutableList.Builder<TypeReference> builder = ImmutableList.builder();
    for (Class<?> parameterType : parameterTypes) {
      builder.add(typeFromClass(parameterType));
    }
    return method(classFromClass(holderClass), "<init>", builder.build(), null);
  }

  /** Get a method reference from class name, method name and signature. */
  public static MethodReference methodFromDescriptor(
      String classDescriptor, String methodName, String methodDescriptor) {
    ImmutableList.Builder<TypeReference> builder = ImmutableList.builder();
    for (String parameterTypeDescriptor :
        DescriptorUtils.getArgumentTypeDescriptors(methodDescriptor)) {
      builder.add(typeFromDescriptor(parameterTypeDescriptor));
    }
    String returnTypeDescriptor = DescriptorUtils.getReturnTypeDescriptor(methodDescriptor);
    return method(
        classFromDescriptor(classDescriptor),
        methodName,
        builder.build(),
        returnTypeDescriptor.equals("V") ? null : typeFromDescriptor(returnTypeDescriptor));
  }

  public static MethodReference classConstructor(ClassReference type) {
    return method(type, "<clinit>", Collections.emptyList(), null);
  }

  /** Get a field reference from its full reference specification. */
  public static FieldReference field(
      ClassReference holderClass, String fieldName, TypeReference fieldType) {
    return new FieldReference(holderClass, fieldName, fieldType);
  }

  /** Get a field reference from a Java reflection field. */
  public static FieldReference fieldFromField(Field field) {
    Class<?> holderClass = field.getDeclaringClass();
    String fieldName = field.getName();
    Class<?> fieldType = field.getType();
    return field(classFromClass(holderClass), fieldName, typeFromClass(fieldType));
  }

  /** Create a package reference from a string */
  public static PackageReference packageFromString(String packageName) {
    // Note, we rely on equality check for packages and do not canonicalize them.
    return new PackageReference(packageName);
  }

  /** Create a package from a java.lang.Package */
  public static PackageReference packageFromPackage(Package pkg) {
    return new PackageReference(pkg.getName());
  }
}
