// Copyright (c) 2019, 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.Kotlin.addKotlinPrefix;
import static com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.parameterTypesFromJvmMethodSignature;
import static com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.returnTypeFromJvmMethodSignature;
import static com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.toJvmMethodSignature;
import static com.android.tools.r8.utils.DescriptorUtils.descriptorToInternalName;
import static com.android.tools.r8.utils.DescriptorUtils.getDescriptorFromKmType;
import static kotlinx.metadata.FlagsKt.flagsOf;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.KmFunctionProcessor;
import com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.KmPropertyProcessor;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import java.util.List;
import kotlinx.metadata.KmConstructor;
import kotlinx.metadata.KmFunction;
import kotlinx.metadata.KmProperty;
import kotlinx.metadata.KmType;
import kotlinx.metadata.KmValueParameter;
import kotlinx.metadata.jvm.JvmMethodSignature;
import kotlinx.metadata.jvm.JvmExtensionsKt;

public class KotlinMetadataSynthesizer {

  static boolean isExtension(KmFunction kmFunction) {
    return kmFunction.getReceiverParameterType() != null;
  }

  static boolean isExtension(KmProperty kmProperty) {
    return kmProperty.getReceiverParameterType() != null;
  }

  static KmType toKmType(String descriptor) {
    KmType kmType = new KmType(flagsOf());
    kmType.visitClass(descriptorToInternalName(descriptor));
    return kmType;
  }

  static KmType toRenamedKmType(
      DexType type, AppView<AppInfoWithLiveness> appView, NamingLens lens) {
    // E.g., [Ljava/lang/String; -> Lkotlin/Array;
    if (type.isArrayType()) {
      return toKmType(addKotlinPrefix("Array;"));
    }
    // E.g., void -> Lkotlin/Unit;
    if (appView.dexItemFactory().kotlin.knownTypeConversion.containsKey(type)) {
      KmType kmType = new KmType(flagsOf());
      DexType convertedType = appView.dexItemFactory().kotlin.knownTypeConversion.get(type);
      assert convertedType != null;
      kmType.visitClass(descriptorToInternalName(convertedType.toDescriptorString()));
      return kmType;
    }
    // For library or classpath class, synthesize @Metadata always.
    // For a program class, make sure it is live.
    if (!appView.appInfo().isNonProgramTypeOrLiveProgramType(type)) {
      return null;
    }
    DexType renamedType = lens.lookupType(type, appView.dexItemFactory());
    // For library or classpath class, we should not have renamed it.
    DexClass clazz = appView.definitionFor(type);
    assert clazz == null || clazz.isProgramClass() || renamedType == type
        : type.toSourceString() + " -> " + renamedType.toSourceString();
    // TODO(b/70169921): Mysterious, why attempts to properly set flags bothers kotlinc?
    //   and/or why wiping out flags works for KmType but not KmFunction?!
    KmType kmType = new KmType(flagsOf());
    kmType.visitClass(descriptorToInternalName(renamedType.toDescriptorString()));
    return kmType;
  }

  private static boolean isCompatible(String desc, DexType type) {
    if (desc == null || type == null) {
      return false;
    }
    return desc.equals(type.toDescriptorString());
  }

  private static boolean isCompatible(KmType kmType, DexType type, AppView<?> appView) {
    if (kmType == null || type == null) {
      return false;
    }
    String descriptor = null;
    if (appView.dexItemFactory().kotlin.knownTypeConversion.containsKey(type)) {
      DexType convertedType = appView.dexItemFactory().kotlin.knownTypeConversion.get(type);
      descriptor = convertedType.toDescriptorString();
    }
    if (descriptor == null) {
      descriptor = type.toDescriptorString();
    }
    assert descriptor != null;
    return descriptor.equals(getDescriptorFromKmType(kmType));
  }

  private static boolean isCompatibleJvmMethodSignature(
      JvmMethodSignature signature, DexEncodedMethod method) {
    String methodName = method.method.name.toString();
    if (!signature.getName().equals(methodName)) {
      return false;
    }
    if (!isCompatible(
        returnTypeFromJvmMethodSignature(signature), method.method.proto.returnType)) {
      return false;
    }
    List<String> parameterTypes = parameterTypesFromJvmMethodSignature(signature);
    if (parameterTypes == null || parameterTypes.size() != method.method.proto.parameters.size()) {
      return false;
    }
    for (int i = 0; i < method.method.proto.parameters.size(); i++) {
      if (!isCompatible(parameterTypes.get(i), method.method.proto.parameters.values[i])) {
        return false;
      }
    }
    return true;
  }

  public static boolean isCompatibleConstructor(
      KmConstructor constructor, DexEncodedMethod method, AppView<?> appView) {
    // Note that targets for @JvmName don't include constructor. So, it's not necessary to process
    // JvmMethodSignature inside JvmConstructorExtension.
    List<KmValueParameter> parameters = constructor.getValueParameters();
    if (method.method.proto.parameters.size() != parameters.size()) {
      return false;
    }
    for (int i = 0; i < method.method.proto.parameters.size(); i++) {
      KmType kmType = parameters.get(i).getType();
      if (!isCompatible(kmType, method.method.proto.parameters.values[i], appView)) {
        return false;
      }
    }
    return true;
  }

  public static boolean isCompatibleFunction(
      KmFunction function, DexEncodedMethod method, AppView<?> appView) {
    // Check if a custom name is set to avoid name clash.
    KmFunctionProcessor kmFunctionProcessor = new KmFunctionProcessor(function);
    JvmMethodSignature jvmMethodSignature = kmFunctionProcessor.signature();
    if (jvmMethodSignature != null && isCompatibleJvmMethodSignature(jvmMethodSignature, method)) {
      return true;
    }

    if (!function.getName().equals(method.method.name.toString())) {
      return false;
    }
    if (!isCompatible(function.getReturnType(), method.method.proto.returnType, appView)) {
      return false;
    }
    List<KmValueParameter> parameters = function.getValueParameters();
    if (method.method.proto.parameters.size() != parameters.size()) {
      return false;
    }
    for (int i = 0; i < method.method.proto.parameters.size(); i++) {
      KmType kmType = parameters.get(i).getType();
      if (!isCompatible(kmType, method.method.proto.parameters.values[i], appView)) {
        return false;
      }
    }
    return true;
  }

  public static boolean isCompatibleExtension(
      KmFunction extension, DexEncodedMethod method, AppView<?> appView) {
    // Check if a custom name is set to avoid name clash.
    KmFunctionProcessor kmFunctionProcessor = new KmFunctionProcessor(extension);
    JvmMethodSignature jvmMethodSignature = kmFunctionProcessor.signature();
    if (jvmMethodSignature != null && isCompatibleJvmMethodSignature(jvmMethodSignature, method)) {
      return true;
    }

    if (!extension.getName().equals(method.method.name.toString())) {
      return false;
    }
    if (!isCompatible(extension.getReturnType(), method.method.proto.returnType, appView)) {
      return false;
    }
    List<KmValueParameter> parameters = extension.getValueParameters();
    if (method.method.proto.parameters.size() != parameters.size() + 1) {
      return false;
    }
    assert method.method.proto.parameters.size() > 0;
    assert extension.getReceiverParameterType() != null;
    if (!isCompatible(
        extension.getReceiverParameterType(), method.method.proto.parameters.values[0], appView)) {
      return false;
    }
    for (int i = 1; i < method.method.proto.parameters.size(); i++) {
      KmType kmType = parameters.get(i - 1).getType();
      if (!isCompatible(kmType, method.method.proto.parameters.values[i], appView)) {
        return false;
      }
    }
    return true;
  }

  public static boolean isCompatibleProperty(
      KmProperty kmProperty, DexEncodedMethod method, AppView<?> appView) {
    KmPropertyProcessor kmPropertyProcessor = new KmPropertyProcessor(kmProperty);
    // Check if a custom getter is defined via @get:JvmName("myGetter").
    JvmMethodSignature getterSignature = kmPropertyProcessor.getterSignature();
    if (getterSignature != null && isCompatibleJvmMethodSignature(getterSignature, method)) {
      return true;
    }
    // Check if a custom setter is defined via @set:JvmName("mySetter").
    JvmMethodSignature setterSignature = kmPropertyProcessor.setterSignature();
    if (setterSignature != null && isCompatibleJvmMethodSignature(setterSignature, method)) {
      return true;
    }

    // E.g., property `prop: T` is mapped to `getProp()T`, `setProp(T)V`, `prop$annotations()V`.
    // For boolean property, though, getter is mapped to `isProp()Z`.
    // TODO(b/70169921): Avoid decoding.
    String methodName = method.method.name.toString();
    if (!methodName.startsWith("is")
        && !methodName.startsWith("get")
        && !methodName.startsWith("set")
        && !methodName.endsWith("$annotations")) {
      return false;
    }

    String propertyName = kmProperty.getName();
    assert propertyName.length() > 0;
    String annotations = propertyName + "$annotations";
    if (methodName.equals(annotations)) {
      return true;
    }
    String capitalized =
        Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
    String returnTypeDescriptor = getDescriptorFromKmType(kmProperty.returnType);
    String getterPrefix =
        returnTypeDescriptor != null && returnTypeDescriptor.endsWith("Boolean;") ? "is" : "get";
    String getter = getterPrefix + capitalized;
    if (methodName.equals(getter)
        && method.method.proto.parameters.size() == 0
        && isCompatible(kmProperty.returnType, method.method.proto.returnType, appView)) {
      return true;
    }
    String setter = "set" + capitalized;
    if (methodName.equals(setter)
        && method.method.proto.returnType.isVoidType()
        && method.method.proto.parameters.size() == 1
        && isCompatible(kmProperty.returnType, method.method.proto.parameters.values[0], appView)) {
      return true;
    }
    return false;
  }

  static KmConstructor toRenamedKmConstructor(
      DexEncodedMethod method,
      AppView<AppInfoWithLiveness> appView,
      NamingLens lens) {
    // Make sure it is an instance initializer and live.
    if (!method.isInstanceInitializer()
        || !appView.appInfo().liveMethods.contains(method.method)) {
      return null;
    }
    KmConstructor kmConstructor = new KmConstructor(method.accessFlags.getAsKotlinFlags());
    JvmExtensionsKt.setSignature(kmConstructor, toJvmMethodSignature(method.method));
    List<KmValueParameter> parameters = kmConstructor.getValueParameters();
    if (!populateKmValueParameters(parameters, method, appView, lens, false)) {
      return null;
    }
    return kmConstructor;
  }

  static KmFunction toRenamedKmFunction(
      DexEncodedMethod method,
      AppView<AppInfoWithLiveness> appView,
      NamingLens lens) {
    return toRenamedKmFunctionHelper(method, appView, lens, false);
  }

  static KmFunction toRenamedKmFunctionAsExtension(
      DexEncodedMethod method,
      AppView<AppInfoWithLiveness> appView,
      NamingLens lens) {
    return toRenamedKmFunctionHelper(method, appView, lens, true);
  }

  private static KmFunction toRenamedKmFunctionHelper(
      DexEncodedMethod method,
      AppView<AppInfoWithLiveness> appView,
      NamingLens lens,
      boolean isExtension) {
    // For library overrides, synthesize @Metadata always.
    // For regular methods, make sure it is live.
    if (!method.isLibraryMethodOverride().isTrue()
        && !appView.appInfo().liveMethods.contains(method.method)) {
      return null;
    }
    DexMethod renamedMethod = lens.lookupMethod(method.method, appView.dexItemFactory());
    // For a library method override, we should not have renamed it.
    assert !method.isLibraryMethodOverride().isTrue() || renamedMethod == method.method
        : method.toSourceString() + " -> " + renamedMethod.toSourceString();
    KmFunction kmFunction =
        new KmFunction(method.accessFlags.getAsKotlinFlags(), renamedMethod.name.toString());
    JvmExtensionsKt.setSignature(kmFunction, toJvmMethodSignature(method.method));
    KmType kmReturnType = toRenamedKmType(method.method.proto.returnType, appView, lens);
    if (kmReturnType == null) {
      return null;
    }
    kmFunction.setReturnType(kmReturnType);
    if (isExtension) {
      assert method.method.proto.parameters.values.length > 0;
      KmType kmReceiverType =
          toRenamedKmType(method.method.proto.parameters.values[0], appView, lens);
      if (kmReceiverType == null) {
        return null;
      }
      kmFunction.setReceiverParameterType(kmReceiverType);
    }
    List<KmValueParameter> parameters = kmFunction.getValueParameters();
    if (!populateKmValueParameters(parameters, method, appView, lens, isExtension)) {
      return null;
    }
    return kmFunction;
  }

  private static boolean populateKmValueParameters(
      List<KmValueParameter> parameters,
      DexEncodedMethod method,
      AppView<AppInfoWithLiveness> appView,
      NamingLens lens,
      boolean isExtension) {
    for (int i = isExtension ? 1 : 0; i < method.method.proto.parameters.values.length; i++) {
      DexType paramType = method.method.proto.parameters.values[i];
      DebugLocalInfo debugLocalInfo = method.getParameterInfo().get(i);
      String parameterName = debugLocalInfo != null ? debugLocalInfo.name.toString() : ("p" + i);
      // TODO(b/70169921): Consult kotlinx.metadata.Flag.ValueParameter.
      KmValueParameter kmValueParameter = new KmValueParameter(flagsOf(), parameterName);
      KmType kmParamType = toRenamedKmType(paramType, appView, lens);
      if (kmParamType == null) {
        return false;
      }
      kmValueParameter.setType(kmParamType);
      parameters.add(kmValueParameter);
    }
    return true;
  }
}
