// 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 com.android.tools.r8.errors.InvalidDescriptorException;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
import com.android.tools.r8.shaking.ProguardKeepRule;
import com.android.tools.r8.shaking.ProguardKeepRuleType;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.TriFunction;
import java.util.List;
import java.util.function.Consumer;
import kotlin.Metadata;
import kotlinx.metadata.KmExtensionType;
import kotlinx.metadata.KmProperty;
import kotlinx.metadata.KmPropertyExtensionVisitor;
import kotlinx.metadata.KmPropertyVisitor;
import kotlinx.metadata.jvm.JvmFieldSignature;
import kotlinx.metadata.jvm.JvmMethodSignature;
import kotlinx.metadata.jvm.JvmPropertyExtensionVisitor;
import kotlinx.metadata.jvm.KotlinClassMetadata;

public class KotlinMetadataUtils {

  private static final NoKotlinInfo NO_KOTLIN_INFO = new NoKotlinInfo("NO_KOTLIN_INFO");
  private static final NoKotlinInfo INVALID_KOTLIN_INFO = new NoKotlinInfo("INVALID_KOTLIN_INFO");

  private static class NoKotlinInfo
      implements KotlinClassLevelInfo, KotlinFieldLevelInfo, KotlinMethodLevelInfo {

    private final String name;

    private NoKotlinInfo(String name) {
      this.name = name;
    }

    @Override
    public String toString() {
      return name;
    }

    @Override
    public Pair<Metadata, Boolean> rewrite(DexClass clazz, AppView<?> appView) {
      throw new Unreachable("Should never be called");
    }

    @Override
    public String getPackageName() {
      throw new Unreachable("Should never be called");
    }

    @Override
    public int[] getMetadataVersion() {
      throw new Unreachable("Should never be called");
    }

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

    @Override
    public void trace(DexDefinitionSupplier definitionSupplier) {
      // No information needed to trace.
    }
  }

  public static NoKotlinInfo getNoKotlinInfo() {
    return NO_KOTLIN_INFO;
  }

  public static NoKotlinInfo getInvalidKotlinInfo() {
    return INVALID_KOTLIN_INFO;
  }

  static JvmFieldSignature toJvmFieldSignature(DexField field) {
    return new JvmFieldSignature(field.name.toString(), field.type.toDescriptorString());
  }

  static JvmMethodSignature toJvmMethodSignature(DexMethod method) {
    StringBuilder descBuilder = new StringBuilder();
    descBuilder.append("(");
    for (DexType argType : method.proto.parameters.values) {
      descBuilder.append(argType.toDescriptorString());
    }
    descBuilder.append(")");
    descBuilder.append(method.proto.returnType.toDescriptorString());
    return new JvmMethodSignature(method.name.toString(), descBuilder.toString());
  }

  static JvmMethodSignature toDefaultJvmMethodSignature(
      JvmMethodSignature methodSignature, int intArguments) {
    return new JvmMethodSignature(
        methodSignature.getName() + "$default",
        methodSignature.getDesc().replace(")", "I".repeat(intArguments) + "Ljava/lang/Object;)"));
  }

  static class KmPropertyProcessor {
    private JvmFieldSignature fieldSignature = null;
    // Custom getter via @get:JvmName("..."). Otherwise, null.
    private JvmMethodSignature getterSignature = null;
    // Custom getter via @set:JvmName("..."). Otherwise, null.
    private JvmMethodSignature setterSignature = null;
    private JvmMethodSignature syntheticMethodForAnnotationsSignature = null;

    KmPropertyProcessor(KmProperty kmProperty) {
      kmProperty.accept(
          new KmPropertyVisitor() {
            @Override
            @SuppressWarnings("ReferenceEquality")
            public KmPropertyExtensionVisitor visitExtensions(KmExtensionType type) {
              if (type != JvmPropertyExtensionVisitor.TYPE) {
                return null;
              }
              return new JvmPropertyExtensionVisitor() {
                @Override
                public void visit(
                    int flags,
                    JvmFieldSignature fieldDesc,
                    JvmMethodSignature getterDesc,
                    JvmMethodSignature setterDesc) {
                  assert fieldSignature == null : fieldSignature.asString();
                  fieldSignature = fieldDesc;
                  assert getterSignature == null : getterSignature.asString();
                  getterSignature = getterDesc;
                  assert setterSignature == null : setterSignature.asString();
                  setterSignature = setterDesc;
                }

                @Override
                public void visitSyntheticMethodForAnnotations(JvmMethodSignature signature) {
                  assert syntheticMethodForAnnotationsSignature == null : signature.asString();
                  syntheticMethodForAnnotationsSignature = signature;
                }
              };
            }
          });
    }

    JvmFieldSignature fieldSignature() {
      return fieldSignature;
    }

    JvmMethodSignature getterSignature() {
      return getterSignature;
    }

    JvmMethodSignature setterSignature() {
      return setterSignature;
    }

    public JvmMethodSignature syntheticMethodForAnnotationsSignature() {
      return syntheticMethodForAnnotationsSignature;
    }
  }

  static boolean isValidMethodDescriptor(String methodDescriptor) {
    try {
      String[] argDescriptors = DescriptorUtils.getArgumentTypeDescriptors(methodDescriptor);
      for (String argDescriptor : argDescriptors) {
        if (argDescriptor.charAt(0) == 'L' && !DescriptorUtils.isClassDescriptor(argDescriptor)) {
          return false;
        }
      }
      return true;
    } catch (InvalidDescriptorException e) {
      return false;
    }
  }

  public static boolean mayProcessKotlinMetadata(AppView<?> appView) {
    // This can run before we have determined the pinned items, because we may need to load the
    // stack-map table on input. This is therefore a conservative guess on kotlin.Metadata is kept.
    DexClass kotlinMetadata =
        appView
            .appInfo()
            .definitionForWithoutExistenceAssert(appView.dexItemFactory().kotlinMetadataType);
    if (kotlinMetadata == null || kotlinMetadata.isNotProgramClass()) {
      return true;
    }
    ProguardConfiguration proguardConfiguration = appView.options().getProguardConfiguration();
    if (proguardConfiguration != null && proguardConfiguration.getRules() != null) {
      for (ProguardConfigurationRule rule : proguardConfiguration.getRules()) {
        if (KotlinMetadataUtils.canBeKotlinMetadataKeepRule(rule, appView.options().itemFactory)) {
          return true;
        }
      }
    }
    return false;
  }

  private static boolean canBeKotlinMetadataKeepRule(
      ProguardConfigurationRule rule, DexItemFactory factory) {
    if (rule.isProguardIfRule()) {
      // For if rules, we simply assume that the precondition can become true.
      return canBeKotlinMetadataKeepRule(rule.asProguardIfRule().getSubsequentRule(), factory);
    }
    if (!rule.isProguardKeepRule()) {
      return false;
    }
    ProguardKeepRule proguardKeepRule = rule.asProguardKeepRule();
    // -keepclassmembers will not in itself keep a class alive.
    if (proguardKeepRule.getType() == ProguardKeepRuleType.KEEP_CLASS_MEMBERS) {
      return false;
    }
    // If the rule allows shrinking, it will not require us to keep the class.
    if (proguardKeepRule.getModifiers().allowsShrinking) {
      return false;
    }
    // Check if the type is matched
    return proguardKeepRule.getClassNames().matches(factory.kotlinMetadataType);
  }

  static String getKotlinClassName(DexClass clazz, String descriptor) {
    InnerClassAttribute innerClassAttribute = clazz.getInnerClassAttributeForThisClass();
    if (innerClassAttribute != null && innerClassAttribute.getOuter() != null) {
      return DescriptorUtils.descriptorToKotlinClassifier(descriptor);
    } else if (clazz.isLocalClass() || clazz.isAnonymousClass()) {
      return getKotlinLocalOrAnonymousNameFromDescriptor(descriptor, true);
    } else {
      // We no longer have an innerclass relationship to maintain and we therefore return a binary
      // name.
      return DescriptorUtils.getBinaryNameFromDescriptor(descriptor);
    }
  }

  static String getKotlinLocalOrAnonymousNameFromDescriptor(
      String descriptor, boolean isLocalOrAnonymous) {
    // For local or anonymous classes, the classifier is prefixed with '.' and inner classes
    // are separated with '$'.
    if (isLocalOrAnonymous) {
      return "." + DescriptorUtils.getBinaryNameFromDescriptor(descriptor);
    }
    return DescriptorUtils.descriptorToKotlinClassifier(descriptor);
  }

  static int[] getCompatibleKotlinInfo() {
    return KotlinClassMetadata.COMPATIBLE_METADATA_VERSION;
  }

  static <TKm> TKm consume(TKm tKm, Consumer<TKm> consumer) {
    consumer.accept(tKm);
    return tKm;
  }

  static <TInfo, TKm> boolean rewriteIfNotNull(
      AppView<?> appView,
      TInfo info,
      Consumer<TKm> newTConsumer,
      TriFunction<TInfo, Consumer<TKm>, AppView<?>, Boolean> rewrite) {
    return info != null ? rewrite.apply(info, newTConsumer, appView) : false;
  }

  static <TInfo, TKm> boolean rewriteList(
      AppView<?> appView,
      List<TInfo> ts,
      List<TKm> newTs,
      TriFunction<TInfo, Consumer<TKm>, AppView<?>, Boolean> rewrite) {
    assert newTs.isEmpty();
    return rewriteList(appView, ts, newTs::add, rewrite);
  }

  static <TInfo, TKm> boolean rewriteList(
      AppView<?> appView,
      List<TInfo> ts,
      Consumer<TKm> newTConsumer,
      TriFunction<TInfo, Consumer<TKm>, AppView<?>, Boolean> rewrite) {
    boolean rewritten = false;
    for (TInfo t : ts) {
      rewritten |= rewrite.apply(t, newTConsumer, appView);
    }
    return rewritten;
  }
}
