// 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.KotlinMetadataUtils.getCompatibleKotlinInfo;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.rewriteList;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.toJvmFieldSignature;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.toJvmMethodSignature;
import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
import static kotlinx.metadata.jvm.KotlinClassMetadata.Companion;

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.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import kotlin.Metadata;
import kotlinx.metadata.KmClass;
import kotlinx.metadata.KmConstructor;
import kotlinx.metadata.KmType;
import kotlinx.metadata.jvm.JvmExtensionsKt;
import kotlinx.metadata.jvm.JvmMethodSignature;
import kotlinx.metadata.jvm.KotlinClassMetadata;

public class KotlinClassInfo implements KotlinClassLevelInfo {

  private final int flags;
  private final String name;
  private final boolean nameCanBeSynthesizedFromClassOrAnonymousObjectOrigin;
  private final String moduleName;
  private final List<KotlinConstructorInfo> constructorsWithNoBacking;
  private final KotlinDeclarationContainerInfo declarationContainerInfo;
  private final List<KotlinTypeParameterInfo> typeParameters;
  private final List<KotlinTypeInfo> superTypes;

  private final List<KotlinTypeReference> sealedSubClasses;

  private final List<KotlinTypeReference> nestedClasses;
  private final List<String> enumEntries;
  private final KotlinVersionRequirementInfo versionRequirements;
  private final KotlinTypeReference anonymousObjectOrigin;
  private final String packageName;
  private final KotlinLocalDelegatedPropertyInfo localDelegatedProperties;
  private final int[] metadataVersion;
  private final String inlineClassUnderlyingPropertyName;
  private final KotlinTypeInfo inlineClassUnderlyingType;
  private final int jvmFlags;
  private final String companionObjectName;
  // Collection of context receiver types
  private final List<KotlinTypeInfo> contextReceiverTypes;

  // List of tracked assignments of kotlin metadata.
  private final KotlinMetadataMembersTracker originalMembersWithKotlinInfo;

  private KotlinClassInfo(
      int flags,
      String name,
      boolean nameCanBeSynthesizedFromClassOrAnonymousObjectOrigin,
      String moduleName,
      KotlinDeclarationContainerInfo declarationContainerInfo,
      List<KotlinTypeParameterInfo> typeParameters,
      List<KotlinConstructorInfo> constructorsWithNoBacking,
      List<KotlinTypeInfo> superTypes,
      List<KotlinTypeReference> sealedSubClasses,
      List<KotlinTypeReference> nestedClasses,
      List<String> enumEntries,
      KotlinVersionRequirementInfo versionRequirements,
      KotlinTypeReference anonymousObjectOrigin,
      String packageName,
      KotlinLocalDelegatedPropertyInfo localDelegatedProperties,
      int[] metadataVersion,
      String inlineClassUnderlyingPropertyName,
      KotlinTypeInfo inlineClassUnderlyingType,
      KotlinMetadataMembersTracker originalMembersWithKotlinInfo,
      int jvmFlags,
      String companionObjectName,
      List<KotlinTypeInfo> contextReceiverTypes) {
    this.flags = flags;
    this.name = name;
    this.nameCanBeSynthesizedFromClassOrAnonymousObjectOrigin =
        nameCanBeSynthesizedFromClassOrAnonymousObjectOrigin;
    this.moduleName = moduleName;
    this.declarationContainerInfo = declarationContainerInfo;
    this.typeParameters = typeParameters;
    this.constructorsWithNoBacking = constructorsWithNoBacking;
    this.superTypes = superTypes;
    this.sealedSubClasses = sealedSubClasses;
    this.nestedClasses = nestedClasses;
    this.enumEntries = enumEntries;
    this.versionRequirements = versionRequirements;
    this.anonymousObjectOrigin = anonymousObjectOrigin;
    this.packageName = packageName;
    this.localDelegatedProperties = localDelegatedProperties;
    this.metadataVersion = metadataVersion;
    this.inlineClassUnderlyingPropertyName = inlineClassUnderlyingPropertyName;
    this.inlineClassUnderlyingType = inlineClassUnderlyingType;
    this.originalMembersWithKotlinInfo = originalMembersWithKotlinInfo;
    this.jvmFlags = jvmFlags;
    this.companionObjectName = companionObjectName;
    this.contextReceiverTypes = contextReceiverTypes;
  }

  public static KotlinClassInfo create(
      KotlinClassMetadata.Class metadata,
      String packageName,
      int[] metadataVersion,
      DexClass hostClass,
      AppView<?> appView,
      Consumer<DexEncodedMethod> keepByteCode) {
    DexItemFactory factory = appView.dexItemFactory();
    Reporter reporter = appView.reporter();
    KmClass kmClass = metadata.getKmClass();
    Map<String, DexEncodedField> fieldMap = new HashMap<>();
    for (DexEncodedField field : hostClass.fields()) {
      fieldMap.put(toJvmFieldSignature(field.getReference()).asString(), field);
    }
    Map<String, DexEncodedMethod> methodMap = new HashMap<>();
    for (DexEncodedMethod method : hostClass.methods()) {
      methodMap.put(toJvmMethodSignature(method.getReference()).asString(), method);
    }
    ImmutableList.Builder<KotlinConstructorInfo> notBackedConstructors = ImmutableList.builder();
    KotlinMetadataMembersTracker originalMembersWithKotlinInfo =
        new KotlinMetadataMembersTracker(appView);
    for (KmConstructor kmConstructor : kmClass.getConstructors()) {
      KotlinConstructorInfo constructorInfo =
          KotlinConstructorInfo.create(kmConstructor, factory, reporter);
      JvmMethodSignature signature = JvmExtensionsKt.getSignature(kmConstructor);
      if (signature != null) {
        DexEncodedMethod method = methodMap.get(signature.asString());
        if (method != null) {
          method.setKotlinMemberInfo(constructorInfo);
          originalMembersWithKotlinInfo.add(method.getReference());
          continue;
        }
      }
      // We could not find a definition for the constructor - add it to ensure the same output.
      notBackedConstructors.add(constructorInfo);
    }
    KotlinDeclarationContainerInfo container =
        KotlinDeclarationContainerInfo.create(
            kmClass,
            methodMap,
            fieldMap,
            factory,
            reporter,
            keepByteCode,
            originalMembersWithKotlinInfo);
    KotlinTypeReference anonymousObjectOrigin = getAnonymousObjectOrigin(kmClass, factory);
    boolean nameCanBeDeducedFromClassOrOrigin =
        kmClass.name.equals(
                KotlinMetadataUtils.getKotlinClassName(
                    hostClass, hostClass.getType().toDescriptorString()))
            || (anonymousObjectOrigin != null
                && kmClass.name.equals(anonymousObjectOrigin.toKotlinClassifier(true)));
    return new KotlinClassInfo(
        kmClass.getFlags(),
        kmClass.name,
        nameCanBeDeducedFromClassOrOrigin,
        JvmExtensionsKt.getModuleName(kmClass),
        container,
        KotlinTypeParameterInfo.create(kmClass.getTypeParameters(), factory, reporter),
        notBackedConstructors.build(),
        getSuperTypes(kmClass.getSupertypes(), factory, reporter),
        getSealedSubClasses(kmClass.getSealedSubclasses(), factory),
        getNestedClasses(hostClass, kmClass.getNestedClasses(), factory),
        setEnumEntries(kmClass, hostClass),
        KotlinVersionRequirementInfo.create(kmClass.getVersionRequirements()),
        anonymousObjectOrigin,
        packageName,
        KotlinLocalDelegatedPropertyInfo.create(
            JvmExtensionsKt.getLocalDelegatedProperties(kmClass), factory, reporter),
        metadataVersion,
        kmClass.getInlineClassUnderlyingPropertyName(),
        KotlinTypeInfo.create(kmClass.getInlineClassUnderlyingType(), factory, reporter),
        originalMembersWithKotlinInfo,
        JvmExtensionsKt.getJvmFlags(kmClass),
        setCompanionObject(kmClass, hostClass, reporter),
        ListUtils.map(
            kmClass.getContextReceiverTypes(),
            contextRecieverType -> KotlinTypeInfo.create(contextRecieverType, factory, reporter)));
  }

  private static KotlinTypeReference getAnonymousObjectOrigin(
      KmClass kmClass, DexItemFactory factory) {
    String anonymousObjectOriginName = JvmExtensionsKt.getAnonymousObjectOriginName(kmClass);
    if (anonymousObjectOriginName != null) {
      return KotlinTypeReference.fromBinaryNameOrKotlinClassifier(
          anonymousObjectOriginName, factory, anonymousObjectOriginName);
    }
    return null;
  }

  private static List<KotlinTypeReference> getNestedClasses(
      DexClass clazz, List<String> nestedClasses, DexItemFactory factory) {
    ImmutableList.Builder<KotlinTypeReference> nestedTypes = ImmutableList.builder();
    for (String nestedClass : nestedClasses) {
      String binaryName =
          clazz.type.toBinaryName() + DescriptorUtils.INNER_CLASS_SEPARATOR + nestedClass;
      nestedTypes.add(
          KotlinTypeReference.fromBinaryNameOrKotlinClassifier(binaryName, factory, nestedClass));
    }
    return nestedTypes.build();
  }

  private static List<KotlinTypeReference> getSealedSubClasses(
      List<String> sealedSubClasses, DexItemFactory factory) {
    ImmutableList.Builder<KotlinTypeReference> sealedTypes = ImmutableList.builder();
    for (String sealedSubClass : sealedSubClasses) {
      String binaryName =
          sealedSubClass.replace(
              DescriptorUtils.JAVA_PACKAGE_SEPARATOR, DescriptorUtils.INNER_CLASS_SEPARATOR);
      sealedTypes.add(
          KotlinTypeReference.fromBinaryNameOrKotlinClassifier(
              binaryName, factory, sealedSubClass));
    }
    return sealedTypes.build();
  }

  private static List<KotlinTypeInfo> getSuperTypes(
      List<KmType> superTypes, DexItemFactory factory, Reporter reporter) {
    ImmutableList.Builder<KotlinTypeInfo> superTypeInfos = ImmutableList.builder();
    for (KmType superType : superTypes) {
      superTypeInfos.add(KotlinTypeInfo.create(superType, factory, reporter));
    }
    return superTypeInfos.build();
  }

  private static String setCompanionObject(KmClass kmClass, DexClass hostClass, Reporter reporter) {
    String companionObjectName = kmClass.getCompanionObject();
    if (companionObjectName == null) {
      return companionObjectName;
    }
    for (DexEncodedField field : hostClass.fields()) {
      if (field.getReference().name.toString().equals(companionObjectName)) {
        field.setKotlinMemberInfo(new KotlinCompanionInfo(companionObjectName));
        return companionObjectName;
      }
    }
    reporter.warning(
        KotlinMetadataDiagnostic.missingCompanionObject(hostClass, companionObjectName));
    return companionObjectName;
  }

  private static List<String> setEnumEntries(KmClass kmClass, DexClass hostClass) {
    List<String> enumEntries = kmClass.getEnumEntries();
    if (enumEntries.isEmpty()) {
      return enumEntries;
    }
    Collection<String> enumEntryStrings =
        enumEntries.size() < 16 ? enumEntries : Sets.newHashSet(enumEntries);
    hostClass
        .fields()
        .forEach(
            field -> {
              String fieldName = field.getName().toString();
              if (enumEntryStrings.contains(fieldName)) {
                field.setKotlinMemberInfo(new KotlinEnumEntryInfo(fieldName));
              }
            });
    return enumEntries;
  }

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

  @Override
  @SuppressWarnings("ReferenceEquality")
  public KotlinClassInfo asClass() {
    return this;
  }

  @Override
  @SuppressWarnings("ReferenceEquality")
  public Pair<Metadata, Boolean> rewrite(DexClass clazz, AppView<?> appView) {
    KmClass kmClass = new KmClass();
    // TODO(b/154348683): Set flags.
    kmClass.setFlags(flags);
    // Set potentially renamed class name.
    DexString originalDescriptor = clazz.type.descriptor;
    DexString rewrittenDescriptor = appView.getNamingLens().lookupDescriptor(clazz.type);
    boolean rewritten = !originalDescriptor.equals(rewrittenDescriptor);
    if (!nameCanBeSynthesizedFromClassOrAnonymousObjectOrigin) {
      kmClass.setName(this.name);
    } else {
      String rewrittenName = null;
      // When the class has an anonymousObjectOrigin and the name equals the identifier there, we
      // keep the name tied to the anonymousObjectOrigin.
      if (anonymousObjectOrigin != null
          && name.equals(anonymousObjectOrigin.toKotlinClassifier(true))) {
        Box<String> rewrittenOrigin = new Box<>();
        anonymousObjectOrigin.toRenamedBinaryNameOrDefault(rewrittenOrigin::set, appView, null);
        if (rewrittenOrigin.isSet()) {
          rewrittenName = "." + rewrittenOrigin.get();
        }
      }
      if (rewrittenName == null) {
        rewrittenName =
            KotlinMetadataUtils.getKotlinClassName(clazz, rewrittenDescriptor.toString());
      }
      kmClass.setName(rewrittenName);
      rewritten |= !name.equals(rewrittenName);
    }
    // Find a companion object.
    boolean foundCompanion = false;
    int numberOfEnumEntries = 0;
    for (DexEncodedField field : clazz.fields()) {
      KotlinFieldLevelInfo kotlinInfo = field.getKotlinInfo();
      if (kotlinInfo.isCompanion()) {
        rewritten |=
            kotlinInfo
                .asCompanion()
                .rewrite(kmClass, field.getReference(), appView.getNamingLens());
        foundCompanion = true;
      } else if (kotlinInfo.isEnumEntry()) {
        KotlinEnumEntryInfo kotlinEnumEntryInfo = kotlinInfo.asEnumEntry();
        rewritten |=
            kotlinEnumEntryInfo.rewrite(kmClass, field.getReference(), appView.getNamingLens());
        if (numberOfEnumEntries >= enumEntries.size()
            || !enumEntries.get(numberOfEnumEntries).equals(kotlinEnumEntryInfo.getEnumEntry())) {
          rewritten = true;
        }
        numberOfEnumEntries += 1;
      }
    }
    // If we did not find a companion but it was there on input we have to emit a new metadata
    // object.
    if (!foundCompanion && companionObjectName != null) {
      rewritten = true;
    }
    // If we could remove enum entries but were unable to rename them we still have to emit a new
    // metadata object.
    if (numberOfEnumEntries < enumEntries.size()) {
      rewritten = true;
    }
    // Take all not backed constructors because we will never find them in definitions.
    for (KotlinConstructorInfo constructorInfo : constructorsWithNoBacking) {
      rewritten |= constructorInfo.rewrite(kmClass, null, appView);
    }
    // Find all constructors.
    KotlinMetadataMembersTracker rewrittenReferences = new KotlinMetadataMembersTracker(appView);
    for (DexEncodedMethod method : clazz.methods()) {
      if (method.getKotlinInfo().isConstructor()) {
        KotlinConstructorInfo constructorInfo = method.getKotlinInfo().asConstructor();
        rewritten |= constructorInfo.rewrite(kmClass, method, appView);
        rewrittenReferences.add(method.getReference());
      }
    }
    // Rewrite functions, type-aliases and type-parameters.
    rewritten |=
        declarationContainerInfo.rewrite(
            kmClass.getFunctions()::add,
            kmClass.getProperties()::add,
            kmClass.getTypeAliases()::add,
            clazz,
            appView,
            rewrittenReferences);
    // Rewrite type parameters.
    rewritten |=
        rewriteList(
            appView, typeParameters, kmClass.getTypeParameters(), KotlinTypeParameterInfo::rewrite);
    // Rewrite super types.
    List<KmType> rewrittenSuperTypes = kmClass.getSupertypes();
    for (KotlinTypeInfo superType : superTypes) {
      // Ensure the rewritten super type is not this type.
      DexType rewrittenSuperType =
          superType.rewriteType(appView.graphLens(), appView.getKotlinMetadataLens());
      if (clazz.getType() != rewrittenSuperType) {
        rewritten |= superType.rewrite(rewrittenSuperTypes::add, appView);
      } else {
        rewritten = true;
      }
    }
    // Rewrite nested classes.
    List<String> rewrittenNestedClasses = kmClass.getNestedClasses();
    for (KotlinTypeReference nestedClass : this.nestedClasses) {
      Box<String> nestedDescriptorBox = new Box<>();
      boolean nestedClassRewritten =
          nestedClass.toRenamedBinaryNameOrDefault(nestedDescriptorBox::set, appView, null);
      if (nestedDescriptorBox.isSet()) {
        if (nestedClassRewritten) {
          // If the class is a nested class, it should be on the form Foo.Bar$Baz, where Baz
          // is the name we should record.
          String nestedDescriptor = nestedDescriptorBox.get();
          int innerClassIndex = nestedDescriptor.lastIndexOf(DescriptorUtils.INNER_CLASS_SEPARATOR);
          rewrittenNestedClasses.add(nestedDescriptor.substring(innerClassIndex + 1));
        } else {
          rewrittenNestedClasses.add(nestedClass.getOriginalName());
        }
      }
      rewritten |= nestedClassRewritten;
    }
    // Rewrite sealed sub-classes.
    List<String> rewrittenSealedClasses = kmClass.getSealedSubclasses();
    for (KotlinTypeReference sealedSubClass : sealedSubClasses) {
      rewritten |=
          sealedSubClass.toRenamedBinaryNameOrDefault(
              sealedName -> {
                if (sealedName != null) {
                  rewrittenSealedClasses.add(
                      sealedName.replace(
                          DescriptorUtils.INNER_CLASS_SEPARATOR,
                          DescriptorUtils.JAVA_PACKAGE_SEPARATOR));
                }
              },
              appView,
              null);
    }
    rewritten |= versionRequirements.rewrite(kmClass.getVersionRequirements()::addAll);
    if (inlineClassUnderlyingPropertyName != null && inlineClassUnderlyingType != null) {
      kmClass.setInlineClassUnderlyingPropertyName(inlineClassUnderlyingPropertyName);
      rewritten |=
          inlineClassUnderlyingType.rewrite(kmClass::setInlineClassUnderlyingType, appView);
    }
    rewritten |=
        rewriteList(
            appView,
            contextReceiverTypes,
            kmClass.getContextReceiverTypes(),
            KotlinTypeInfo::rewrite);
    JvmExtensionsKt.setJvmFlags(kmClass, jvmFlags);
    JvmExtensionsKt.setModuleName(kmClass, moduleName);
    if (anonymousObjectOrigin != null) {
      rewritten |=
          anonymousObjectOrigin.toRenamedBinaryNameOrDefault(
              renamedAnon -> {
                if (renamedAnon != null) {
                  JvmExtensionsKt.setAnonymousObjectOriginName(kmClass, renamedAnon);
                }
              },
              appView,
              null);
    }
    rewritten |=
        localDelegatedProperties.rewrite(
            JvmExtensionsKt.getLocalDelegatedProperties(kmClass)::add, appView);
    return Pair.create(
        Companion.writeClass(kmClass, getCompatibleKotlinInfo(), 0),
        rewritten || !originalMembersWithKotlinInfo.isEqual(rewrittenReferences, appView));
  }

  @Override
  public String getPackageName() {
    return packageName;
  }

  @Override
  public int[] getMetadataVersion() {
    return metadataVersion;
  }

  @Override
  public void trace(DexDefinitionSupplier definitionSupplier) {
    forEachApply(constructorsWithNoBacking, constructor -> constructor::trace, definitionSupplier);
    declarationContainerInfo.trace(definitionSupplier);
    forEachApply(typeParameters, param -> param::trace, definitionSupplier);
    forEachApply(superTypes, type -> type::trace, definitionSupplier);
    forEachApply(sealedSubClasses, sealedClass -> sealedClass::trace, definitionSupplier);
    forEachApply(nestedClasses, nested -> nested::trace, definitionSupplier);
    forEachApply(contextReceiverTypes, nested -> nested::trace, definitionSupplier);
    localDelegatedProperties.trace(definitionSupplier);
    // TODO(b/154347404): trace enum entries.
    if (anonymousObjectOrigin != null) {
      anonymousObjectOrigin.trace(definitionSupplier);
    }
  }
}
