// 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.kotlin;

import static com.android.tools.r8.kotlin.KotlinMemberInfo.MemberKind.CONSTRUCTOR;
import static com.android.tools.r8.kotlin.KotlinMemberInfo.MemberKind.EXTENSION_FUNCTION;
import static com.android.tools.r8.kotlin.KotlinMemberInfo.MemberKind.EXTENSION_PROPERTY_GETTER;
import static com.android.tools.r8.kotlin.KotlinMemberInfo.MemberKind.EXTENSION_PROPERTY_SETTER;
import static com.android.tools.r8.kotlin.KotlinMemberInfo.MemberKind.FUNCTION;
import static com.android.tools.r8.kotlin.KotlinMemberInfo.MemberKind.PROPERTY_GETTER;
import static com.android.tools.r8.kotlin.KotlinMemberInfo.MemberKind.PROPERTY_SETTER;
import static com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.getJvmMethodSignature;
import static com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.toJvmFieldSignature;
import static com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.toJvmMethodSignature;
import static com.android.tools.r8.kotlin.KotlinMetadataSynthesizer.isExtension;

import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.KmPropertyProcessor;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import kotlinx.metadata.KmConstructor;
import kotlinx.metadata.KmDeclarationContainer;
import kotlinx.metadata.KmFunction;
import kotlinx.metadata.KmProperty;
import kotlinx.metadata.KmTypeParameter;
import kotlinx.metadata.KmValueParameter;
import kotlinx.metadata.jvm.JvmMethodSignature;

// Provides access to field/method-level Kotlin information.
public abstract class KotlinMemberInfo {

  private static final List<KotlinValueParameterInfo> EMPTY_VALUE_PARAM_INFO = ImmutableList.of();
  static final List<KotlinTypeParameterInfo> EMPTY_TYPE_PARAM_INFO = ImmutableList.of();

  private static final KotlinMemberInfo NO_KOTLIN_MEMBER_INFO = new NoKotlinMemberInfo();

  public static KotlinMemberInfo getNoKotlinMemberInfo() {
    return NO_KOTLIN_MEMBER_INFO;
  }

  public final MemberKind memberKind;
  // Original member flags. May be necessary to keep Kotlin-specific flag, e.g., suspend function.
  final int flags;

  private KotlinMemberInfo(MemberKind memberKind, int flags) {
    this.memberKind = memberKind;
    this.flags = flags;
  }

  public boolean isFunctionInfo() {
    return false;
  }

  public KotlinFunctionInfo asFunctionInfo() {
    return null;
  }

  public boolean isFieldInfo() {
    return false;
  }

  public KotlinFieldInfo asFieldInfo() {
    return null;
  }

  public boolean isPropertyInfo() {
    return false;
  }

  public KotlinPropertyInfo asPropertyInfo() {
    return null;
  }

  private static class NoKotlinMemberInfo extends KotlinMemberInfo {

    private NoKotlinMemberInfo() {
      super(MemberKind.NONE, 0);
    }
  }

  public static class KotlinFunctionInfo extends KotlinMemberInfo {

    // Information from original KmValueParameter(s) if available.
    final List<KotlinValueParameterInfo> valueParameterInfos;
    // Information from original KmFunction.returnType. Null if this is from a KmConstructor.
    public final KotlinTypeInfo returnType;
    // Information from original KmFunction.receiverType. Null if this is from a KmConstructor.
    final KotlinTypeInfo receiverParameterType;
    // Information about original type parameters. Null if this is from a KmConstructor.
    final List<KotlinTypeParameterInfo> kotlinTypeParameterInfo;

    private KotlinFunctionInfo(
        MemberKind memberKind,
        int flags,
        KotlinTypeInfo returnType,
        KotlinTypeInfo receiverParameterType,
        List<KotlinValueParameterInfo> valueParameterInfos,
        List<KotlinTypeParameterInfo> kotlinTypeParameterInfo) {
      super(memberKind, flags);
      assert memberKind.isFunction() || memberKind.isConstructor();
      this.returnType = returnType;
      this.receiverParameterType = receiverParameterType;
      this.valueParameterInfos = valueParameterInfos;
      this.kotlinTypeParameterInfo = kotlinTypeParameterInfo;
    }

    KotlinValueParameterInfo getValueParameterInfo(int i) {
      if (valueParameterInfos.isEmpty()) {
        return null;
      }
      if (i < 0 || i >= valueParameterInfos.size()) {
        return null;
      }
      return valueParameterInfos.get(i);
    }

    @Override
    public boolean isFunctionInfo() {
      return true;
    }

    @Override
    public KotlinFunctionInfo asFunctionInfo() {
      return this;
    }
  }

  public static class KotlinFieldInfo extends KotlinMemberInfo {

    // Original property name for (extension) property. Otherwise, null.
    final String propertyName;

    private KotlinFieldInfo(MemberKind memberKind, int flags, String propertyName) {
      super(memberKind, flags);
      this.propertyName = propertyName;
    }

    @Override
    public boolean isFieldInfo() {
      return true;
    }

    @Override
    public KotlinFieldInfo asFieldInfo() {
      return this;
    }
  }

  public static class KotlinPropertyInfo extends KotlinMemberInfo {

    // Original getter flags. E.g., for property getter.
    final int getterFlags;

    // Original setter flags. E.g., for property setter.
    final int setterFlags;

    // Original property name for (extension) property. Otherwise, null.
    final String propertyName;

    // Original return type information. This should never be NULL (even for setters without field).
    final KotlinTypeInfo returnType;

    // Information from original KmValueParameter if available.
    final KotlinValueParameterInfo valueParameterInfo;

    private KotlinPropertyInfo(
        MemberKind memberKind,
        int flags,
        int getterFlags,
        int setterFlags,
        String propertyName,
        KotlinTypeInfo returnType,
        KotlinValueParameterInfo valueParameterInfo) {
      super(memberKind, flags);
      this.getterFlags = getterFlags;
      this.setterFlags = setterFlags;
      this.propertyName = propertyName;
      this.returnType = returnType;
      this.valueParameterInfo = valueParameterInfo;
    }

    @Override
    public KotlinPropertyInfo asPropertyInfo() {
      return this;
    }

    @Override
    public boolean isPropertyInfo() {
      return true;
    }
  }

  private static KotlinFunctionInfo createFunctionInfoFromConstructor(KmConstructor kmConstructor) {
    return new KotlinFunctionInfo(
        CONSTRUCTOR,
        kmConstructor.getFlags(),
        null,
        null,
        getValueParameters(kmConstructor.getValueParameters()),
        EMPTY_TYPE_PARAM_INFO);
  }

  private static KotlinFunctionInfo createFunctionInfo(
      MemberKind memberKind, KmFunction kmFunction) {
    assert memberKind.isFunction();
    KotlinTypeInfo returnTypeInfo = KotlinTypeInfo.create(kmFunction.getReturnType());
    KotlinTypeInfo receiverParameterTypeInfo =
        KotlinTypeInfo.create(kmFunction.getReceiverParameterType());
    return new KotlinFunctionInfo(
        memberKind,
        kmFunction.getFlags(),
        returnTypeInfo,
        receiverParameterTypeInfo,
        getValueParameters(kmFunction.getValueParameters()),
        getTypeParameters(kmFunction.getTypeParameters()));
  }

  private static List<KotlinValueParameterInfo> getValueParameters(
      List<KmValueParameter> parameters) {
    if (parameters.isEmpty()) {
      return EMPTY_VALUE_PARAM_INFO;
    }
    ImmutableList.Builder<KotlinValueParameterInfo> builder = ImmutableList.builder();
    for (KmValueParameter kmValueParameter : parameters) {
      builder.add(KotlinValueParameterInfo.fromKmValueParameter(kmValueParameter));
    }
    return builder.build();
  }

  private static List<KotlinTypeParameterInfo> getTypeParameters(List<KmTypeParameter> parameters) {
    if (parameters.isEmpty()) {
      return EMPTY_TYPE_PARAM_INFO;
    }
    ImmutableList.Builder<KotlinTypeParameterInfo> builder = ImmutableList.builder();
    for (KmTypeParameter kmTypeParameter : parameters) {
      builder.add(KotlinTypeParameterInfo.fromKmTypeParameter(kmTypeParameter));
    }
    return builder.build();
  }

  private static KotlinFieldInfo createFieldInfo(MemberKind memberKind, KmProperty kmProperty) {
    assert memberKind.isBackingField() || memberKind.isBackingFieldForCompanionObject();
    return new KotlinFieldInfo(memberKind, kmProperty.getFlags(), kmProperty.getName());
  }

  private static KotlinPropertyInfo createPropertyInfo(
      MemberKind memberKind, KmProperty kmProperty) {
    assert memberKind.isProperty();
    return new KotlinPropertyInfo(
        memberKind,
        kmProperty.getFlags(),
        kmProperty.getGetterFlags(),
        kmProperty.getSetterFlags(),
        kmProperty.getName(),
        KotlinTypeInfo.create(kmProperty.getReturnType()),
        KotlinValueParameterInfo.fromKmValueParameter(kmProperty.getSetterParameter()));
  }

  public enum MemberKind {
    NONE,

    CONSTRUCTOR,
    FUNCTION,
    EXTENSION_FUNCTION,

    COMPANION_OBJECT_BACKING_FIELD,
    PROPERTY_BACKING_FIELD,
    PROPERTY_GETTER,
    PROPERTY_SETTER,
    PROPERTY_ANNOTATIONS,

    // No backing field for extension property.
    EXTENSION_PROPERTY_GETTER,
    EXTENSION_PROPERTY_SETTER,
    EXTENSION_PROPERTY_ANNOTATIONS;

    public boolean isConstructor() {
      return this == CONSTRUCTOR;
    }

    public boolean isFunction() {
      return this == FUNCTION || isExtensionFunction();
    }

    public boolean isExtensionFunction() {
      return this == EXTENSION_FUNCTION;
    }

    public boolean isBackingField() {
      return this == PROPERTY_BACKING_FIELD;
    }

    public boolean isBackingFieldForCompanionObject() {
      return this == COMPANION_OBJECT_BACKING_FIELD;
    }

    public boolean isProperty() {
      return isBackingField()
          || isBackingFieldForCompanionObject()
          || this == PROPERTY_GETTER
          || this == PROPERTY_SETTER
          || this == PROPERTY_ANNOTATIONS
          || isExtensionProperty();
    }

    public boolean isExtensionProperty() {
      return this == EXTENSION_PROPERTY_GETTER
          || this == EXTENSION_PROPERTY_SETTER
          || this == EXTENSION_PROPERTY_ANNOTATIONS;
    }
  }

  static void markKotlinMemberInfo(DexClass clazz, KotlinInfo kotlinInfo, Reporter reporter) {
    if (kotlinInfo == null || !kotlinInfo.hasDeclarations()) {
      return;
    }

    Map<String, KmConstructor> kmConstructorMap = new HashMap<>();
    Map<String, KmFunction> kmFunctionMap = new HashMap<>();
    Map<String, KmProperty> kmPropertyFieldMap = new HashMap<>();
    Map<String, KmProperty> kmPropertyGetterMap = new HashMap<>();
    Map<String, KmProperty> kmPropertySetterMap = new HashMap<>();

    KmDeclarationContainer kmDeclarationContainer = kotlinInfo.getDeclarations();
    String companionObject = null;
    if (kotlinInfo.isClass()) {
      companionObject = kotlinInfo.asClass().kmClass.getCompanionObject();
      kotlinInfo
          .asClass()
          .kmClass
          .getConstructors()
          .forEach(
              kmConstructor -> {
                JvmMethodSignature methodSignature = getJvmMethodSignature(kmConstructor, reporter);
                if (methodSignature != null) {
                  kmConstructorMap.put(methodSignature.asString(), kmConstructor);
                }
              });
    }
    kmDeclarationContainer
        .getFunctions()
        .forEach(
            kmFunction -> {
              JvmMethodSignature methodSignature = getJvmMethodSignature(kmFunction, reporter);
              if (methodSignature != null) {
                kmFunctionMap.put(methodSignature.asString(), kmFunction);
              }
            });
    kmDeclarationContainer.getProperties().forEach(kmProperty -> {
      KmPropertyProcessor propertyProcessor = new KmPropertyProcessor(kmProperty, reporter);
      if (propertyProcessor.fieldSignature() != null) {
        kmPropertyFieldMap.put(propertyProcessor.fieldSignature().asString(), kmProperty);
      }
      if (propertyProcessor.getterSignature() != null) {
        kmPropertyGetterMap.put(propertyProcessor.getterSignature().asString(), kmProperty);
      }
      if (propertyProcessor.setterSignature() != null) {
        kmPropertySetterMap.put(propertyProcessor.setterSignature().asString(), kmProperty);
      }
      // TODO(b/151194869): property annotations
    });

    for (DexEncodedField field : clazz.fields()) {
      if (companionObject != null && companionObject.equals(field.field.name.toString())) {
        assert kotlinInfo.isClass();
        kotlinInfo.asClass().foundCompanionObject(field);
        continue;
      }
      String key = toJvmFieldSignature(field.field).asString();
      if (kmPropertyFieldMap.containsKey(key)) {
        KmProperty kmProperty = kmPropertyFieldMap.get(key);
        field.setKotlinMemberInfo(
            createFieldInfo(
                clazz == kotlinInfo.clazz
                    ? MemberKind.PROPERTY_BACKING_FIELD
                    : MemberKind.COMPANION_OBJECT_BACKING_FIELD,
                kmProperty));
      }
    }

    for (DexEncodedMethod method : clazz.methods()) {
      String key = toJvmMethodSignature(method.method).asString();
      if (kmConstructorMap.containsKey(key)) {
        // Interestingly we cannot assert that the method is a jvm initializer, because the jvm
        // signature can be a different.
        method.setKotlinMemberInfo(createFunctionInfoFromConstructor(kmConstructorMap.get(key)));
      } else if (kmFunctionMap.containsKey(key)) {
        KmFunction kmFunction = kmFunctionMap.get(key);
        method.setKotlinMemberInfo(
            createFunctionInfo(
                isExtension(kmFunction) ? EXTENSION_FUNCTION : FUNCTION, kmFunction));
      } else if (kmPropertyGetterMap.containsKey(key)) {
        KmProperty kmProperty = kmPropertyGetterMap.get(key);
        method.setKotlinMemberInfo(
            createPropertyInfo(
                isExtension(kmProperty) ? EXTENSION_PROPERTY_GETTER : PROPERTY_GETTER, kmProperty));
      } else if (kmPropertySetterMap.containsKey(key)) {
        KmProperty kmProperty = kmPropertySetterMap.get(key);
        method.setKotlinMemberInfo(
            createPropertyInfo(
                isExtension(kmProperty) ? EXTENSION_PROPERTY_SETTER : PROPERTY_SETTER, kmProperty));
      }
    }
  }
}
