// 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.utils.codeinspector;

import static com.android.tools.r8.KotlinTestBase.METADATA_TYPE;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import com.android.tools.r8.TestRuntime.CfRuntime;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.graph.AccessFlags;
import com.android.tools.r8.graph.DexAnnotation;
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.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.kotlin.KotlinClassMetadataReader;
import com.android.tools.r8.naming.ClassNamingForNameMapper;
import com.android.tools.r8.naming.MemberNaming;
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.naming.mappinginformation.MappingInformation;
import com.android.tools.r8.naming.signature.GenericSignatureParser;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.references.TypeReference;
import com.android.tools.r8.retrace.RetraceClassElement;
import com.android.tools.r8.retrace.RetraceClassResult;
import com.android.tools.r8.retrace.RetraceTypeResult;
import com.android.tools.r8.retrace.RetracedFieldReference;
import com.android.tools.r8.retrace.Retracer;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.ZipUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector.MappingWrapper;
import com.google.common.collect.Sets;
import java.io.File;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import kotlinx.metadata.jvm.KotlinClassMetadata;
import org.junit.rules.TemporaryFolder;

public class FoundClassSubject extends ClassSubject {

  private final DexClass dexClass;
  private final MappingWrapper mapping;

  FoundClassSubject(
      CodeInspector codeInspector,
      DexClass dexClass,
      MappingWrapper mapping,
      ClassReference reference) {
    super(codeInspector, reference);
    this.dexClass = dexClass;
    this.mapping = mapping;
  }

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

  @Override
  public void forAllMethods(Consumer<FoundMethodSubject> inspection) {
    CodeInspector.forAll(
        dexClass.directMethods(),
        (encoded, clazz) -> new FoundMethodSubject(codeInspector, encoded, clazz),
        this,
        inspection);
    forAllVirtualMethods(inspection);
  }

  @Override
  public void forAllVirtualMethods(Consumer<FoundMethodSubject> inspection) {
    CodeInspector.forAll(
        dexClass.virtualMethods(),
        (encoded, clazz) -> new FoundMethodSubject(codeInspector, encoded, clazz),
        this,
        inspection);
  }

  @Override
  public MethodSubject method(String returnType, String name, List<String> parameters) {
    DexType[] parameterTypes = new DexType[parameters.size()];
    for (int i = 0; i < parameters.size(); i++) {
      parameterTypes[i] =
          codeInspector.toDexType(codeInspector.getObfuscatedTypeName(parameters.get(i)));
    }
    DexProto proto =
        codeInspector.dexItemFactory.createProto(
            codeInspector.toDexType(codeInspector.getObfuscatedTypeName(returnType)), parameterTypes);
    if (getNaming() != null) {
      Signature signature =
          new MethodSignature(name, returnType, parameters.toArray(StringUtils.EMPTY_ARRAY));
      MemberNaming methodNaming = getNaming().lookupByOriginalSignature(signature);
      if (methodNaming != null) {
        name = methodNaming.getRenamedName();
      }
    }
    DexMethod dexMethod =
        codeInspector.dexItemFactory.createMethod(
            dexClass.type, proto, codeInspector.dexItemFactory.createString(name));
    DexEncodedMethod encoded = findMethod(dexClass.directMethods(), dexMethod);
    if (encoded == null) {
      encoded = findMethod(dexClass.virtualMethods(), dexMethod);
    }
    return encoded == null
        ? new AbsentMethodSubject()
        : new FoundMethodSubject(codeInspector, encoded, this);
  }

  private DexEncodedMethod findMethod(Iterable<DexEncodedMethod> methods, DexMethod dexMethod) {
    for (DexEncodedMethod method : methods) {
      if (method.getReference().equals(dexMethod)) {
        return method;
      }
    }
    return null;
  }

  @Override
  public MethodSubject uniqueMethodThatMatches(Predicate<FoundMethodSubject> predicate) {
    MethodSubject methodSubject = null;
    for (FoundMethodSubject candidate : allMethods(predicate)) {
      assert methodSubject == null;
      methodSubject = candidate;
    }
    return methodSubject != null ? methodSubject : new AbsentMethodSubject();
  }

  @Override
  public MethodSubject uniqueMethodWithName(String name) {
    MethodSubject methodSubject = null;
    for (FoundMethodSubject candidate : allMethods()) {
      if (candidate.getOriginalName(false).equals(name)) {
        assert methodSubject == null;
        methodSubject = candidate;
      }
    }
    return methodSubject != null ? methodSubject : new AbsentMethodSubject();
  }

  @Override
  public MethodSubject uniqueMethodWithFinalName(String name) {
    MethodSubject methodSubject = null;
    for (FoundMethodSubject candidate : allMethods()) {
      if (candidate.getFinalName().equals(name)) {
        assert methodSubject == null;
        methodSubject = candidate;
      }
    }
    return methodSubject != null ? methodSubject : new AbsentMethodSubject();
  }

  @Override
  public void forAllFields(Consumer<FoundFieldSubject> inspection) {
    forAllInstanceFields(inspection);
    forAllStaticFields(inspection);
  }

  @Override
  public void forAllInstanceFields(Consumer<FoundFieldSubject> inspection) {
    CodeInspector.forAll(
        dexClass.instanceFields(),
        (dexField, clazz) -> new FoundFieldSubject(codeInspector, dexField, clazz),
        this,
        inspection);
  }

  @Override
  public void forAllStaticFields(Consumer<FoundFieldSubject> inspection) {
    CodeInspector.forAll(
        dexClass.staticFields(),
        (dexField, clazz) -> new FoundFieldSubject(codeInspector, dexField, clazz),
        this,
        inspection);
  }

  @Override
  public FieldSubject field(String type, String name) {
    String obfuscatedType = codeInspector.getObfuscatedTypeName(type);
    MemberNaming fieldNaming = null;
    if (getNaming() != null) {
      fieldNaming = getNaming().lookupByOriginalSignature(new FieldSignature(name, type));
    }
    String obfuscatedName = fieldNaming == null ? name : fieldNaming.getRenamedName();

    DexField field =
        codeInspector.dexItemFactory.createField(
            dexClass.type,
            codeInspector.toDexType(obfuscatedType),
            codeInspector.dexItemFactory.createString(obfuscatedName));
    DexEncodedField encoded = findField(dexClass.staticFields(), field);
    if (encoded == null) {
      encoded = findField(dexClass.instanceFields(), field);
    }
    return encoded == null
        ? new AbsentFieldSubject()
        : new FoundFieldSubject(codeInspector, encoded, this);
  }

  @Override
  public FieldSubject uniqueFieldWithName(String name) {
    return uniqueFieldWithName(name, null);
  }

  // TODO(b/169882658): This should be removed when we have identity mappings for ambiguous cases.
  public FieldSubject uniqueFieldWithName(String name, TypeReference originalType) {
    Retracer retracer = codeInspector.retrace();
    Set<FoundFieldSubject> candidates = Sets.newIdentityHashSet();
    Set<FoundFieldSubject> sameTypeCandidates = Sets.newIdentityHashSet();
    for (FoundFieldSubject candidate : allFields()) {
      FieldReference fieldReference = candidate.getDexField().asFieldReference();
      // TODO(b/169882658): This if should be removed completely.
      if (candidate.getFinalName().equals(name)) {
        candidates.add(candidate);
        if (isNullOrEqual(originalType, fieldReference.getFieldType())) {
          sameTypeCandidates.add(candidate);
        }
      }
      retracer
          .retraceField(fieldReference)
          .forEach(
              element -> {
                RetracedFieldReference field = element.getField();
                if (!element.isUnknown() && field.getFieldName().equals(name)) {
                  candidates.add(candidate);
                  // TODO(b/169953605): There should not be a need for mapping the final type.
                  TypeReference fieldOriginalType = originalType;
                  if (fieldOriginalType == null) {
                    RetraceTypeResult retraceTypeResult =
                        retracer.retraceType(fieldReference.getFieldType());
                    assert !retraceTypeResult.isAmbiguous();
                    fieldOriginalType =
                        retraceTypeResult.stream().iterator().next().getType().getTypeReference();
                  }
                  if (isNullOrEqual(fieldOriginalType, field.asKnown().getFieldType())) {
                    sameTypeCandidates.add(candidate);
                  }
                }
              });
    }
    assert candidates.size() >= sameTypeCandidates.size();
    // If we have any merged types we cannot rely on sameTypeCandidates, so we look in all
    // candidates first.
    if (candidates.size() == 1) {
      return candidates.iterator().next();
    }
    return sameTypeCandidates.size() == 1
        ? sameTypeCandidates.iterator().next()
        : new AbsentFieldSubject();
  }

  private boolean isNullOrEqual(TypeReference original, TypeReference rewritten) {
    return original == null || original.equals(rewritten);
  }

  @Override
  public FieldSubject uniqueFieldWithFinalName(String name) {
    FieldSubject fieldSubject = null;
    for (FoundFieldSubject candidate : allFields()) {
      if (candidate.getFinalName().equals(name)) {
        assert fieldSubject == null;
        fieldSubject = candidate;
      }
    }
    return fieldSubject != null ? fieldSubject : new AbsentFieldSubject();
  }

  @Override
  public FoundClassSubject asFoundClassSubject() {
    return this;
  }

  @Override
  public boolean isAbstract() {
    return dexClass.accessFlags.isAbstract();
  }

  @Override
  public boolean isImplementing(ClassSubject subject) {
    assertTrue(subject.isPresent());
    for (DexType itf : getDexProgramClass().interfaces) {
      if (itf.toSourceString().equals(subject.getFinalName())) {
        return true;
      }
    }
    return false;
  }

  @Override
  public boolean isImplementing(Class<?> clazz) {
    return isImplementing(clazz.getTypeName());
  }

  @Override
  public boolean isImplementing(String javaTypeName) {
    for (DexType itf : getDexProgramClass().interfaces) {
      if (itf.toSourceString().equals(javaTypeName)) {
        return true;
      }
    }
    return false;
  }

  @Override
  public boolean isAnnotation() {
    return dexClass.accessFlags.isAnnotation();
  }

  private DexEncodedField findField(List<DexEncodedField> fields, DexField dexField) {
    for (DexEncodedField field : fields) {
      if (field.getReference().equals(dexField)) {
        return field;
      }
    }
    return null;
  }

  @Override
  public DexProgramClass getDexProgramClass() {
    assert dexClass.isProgramClass();
    return dexClass.asProgramClass();
  }

  public ClassSubject getSuperClass() {
    return codeInspector.clazz(dexClass.superType.toSourceString());
  }

  @Override
  public AnnotationSubject annotation(String name) {
    // Ensure we don't check for annotations represented as attributes.
    assert !name.endsWith("EnclosingClass")
        && !name.endsWith("EnclosingMethod")
        && !name.endsWith("InnerClass");
    DexAnnotation annotation = codeInspector.findAnnotation(name, dexClass.annotations());
    return annotation == null
        ? new AbsentAnnotationSubject()
        : new FoundAnnotationSubject(annotation);
  }

  @Override
  public AccessFlags<?> getAccessFlags() {
    return getDexProgramClass().getAccessFlags();
  }

  @Override
  public String getOriginalName() {
    if (getNaming() != null) {
      return getNaming().originalName;
    } else {
      return getFinalName();
    }
  }

  @Override
  public String getOriginalDescriptor() {
    if (getNaming() != null) {
      return DescriptorUtils.javaTypeToDescriptor(getNaming().originalName);
    } else {
      return getFinalDescriptor();
    }
  }

  @Override
  public String getOriginalBinaryName() {
    return DescriptorUtils.getBinaryNameFromDescriptor(getOriginalDescriptor());
  }

  public DexType getOriginalDexType(DexItemFactory dexItemFactory) {
    return dexItemFactory.createType(getOriginalDescriptor());
  }

  @Override
  public ClassReference getOriginalReference() {
    return Reference.classFromDescriptor(getOriginalDescriptor());
  }

  @Override
  public ClassReference getFinalReference() {
    return Reference.classFromDescriptor(getFinalDescriptor());
  }

  @Override
  public String getFinalName() {
    return DescriptorUtils.descriptorToJavaType(getFinalDescriptor());
  }

  @Override
  public String getFinalDescriptor() {
    return dexClass.type.descriptor.toString();
  }

  @Override
  public String getFinalBinaryName() {
    return DescriptorUtils.getBinaryNameFromDescriptor(getFinalDescriptor());
  }

  @Override
  public boolean isRenamed() {
    return getNaming() != null && !getFinalDescriptor().equals(getOriginalDescriptor());
  }

  @Override
  public boolean isCompilerSynthesized() {
    for (MappingInformation info : mapping.getAdditionalMappings()) {
      if (info.isCompilerSynthesizedMappingInformation()) {
        return true;
      }
    }
    return false;
  }

  @Override
  public boolean isLocalClass() {
    return dexClass.isLocalClass();
  }

  @Override
  public boolean isMemberClass() {
    return dexClass.isMemberClass();
  }

  @Override
  public boolean isAnonymousClass() {
    return dexClass.isAnonymousClass();
  }

  @Override
  public boolean isSynthesizedJavaLambdaClass() {
    // TODO(141287349): Make this precise based on the map input.
    return SyntheticItemsTestUtils.isExternalLambda(getOriginalReference())
        || SyntheticItemsTestUtils.isExternalLambda(getFinalReference());
  }

  @Override
  public DexMethod getFinalEnclosingMethod() {
    return dexClass.getEnclosingMethodAttribute().getEnclosingMethod();
  }

  @Override
  public String getOriginalSignatureAttribute() {
    return codeInspector.getOriginalSignatureAttribute(
        dexClass.getClassSignature().toString(), GenericSignatureParser::parseClassSignature);
  }

  @Override
  public String getFinalSignatureAttribute() {
    return dexClass.getClassSignature().toString();
  }

  @Override
  public int hashCode() {
    int result = codeInspector.hashCode();
    result = 31 * result + dexClass.hashCode();
    result = 31 * result + (getNaming() != null ? getNaming().hashCode() : 0);
    return result;
  }

  @Override
  public boolean equals(Object other) {
    if (other == null || other.getClass() != this.getClass()) {
      return false;
    }
    FoundClassSubject otherSubject = (FoundClassSubject) other;
    return codeInspector == otherSubject.codeInspector
        && dexClass == otherSubject.dexClass
        && getNaming() == otherSubject.getNaming();
  }

  @Override
  public String toString() {
    return dexClass.toSourceString();
  }

  public TypeSubject asTypeSubject() {
    return new TypeSubject(codeInspector, getDexProgramClass().type);
  }

  @Override
  public KmClassSubject getKmClass() {
    AnnotationSubject annotationSubject = annotation(METADATA_TYPE);
    if (!annotationSubject.isPresent()) {
      return new AbsentKmClassSubject();
    }
    KotlinClassMetadata metadata =
        KotlinClassMetadataReader.toKotlinClassMetadata(
            codeInspector.getFactory().kotlin, annotationSubject.getAnnotation());
    assertTrue(metadata instanceof KotlinClassMetadata.Class);
    KotlinClassMetadata.Class kClass = (KotlinClassMetadata.Class) metadata;
    return new FoundKmClassSubject(codeInspector, getDexProgramClass(), kClass.toKmClass());
  }

  @Override
  public KmPackageSubject getKmPackage() {
    AnnotationSubject annotationSubject = annotation(METADATA_TYPE);
    if (!annotationSubject.isPresent()) {
      return new AbsentKmPackageSubject();
    }
    KotlinClassMetadata metadata =
        KotlinClassMetadataReader.toKotlinClassMetadata(
            codeInspector.getFactory().kotlin, annotationSubject.getAnnotation());
    assertTrue(metadata instanceof KotlinClassMetadata.FileFacade
        || metadata instanceof KotlinClassMetadata.MultiFileClassPart);
    if (metadata instanceof KotlinClassMetadata.FileFacade) {
      KotlinClassMetadata.FileFacade kFile = (KotlinClassMetadata.FileFacade) metadata;
      return new FoundKmPackageSubject(codeInspector, getDexProgramClass(), kFile.toKmPackage());
    } else {
      KotlinClassMetadata.MultiFileClassPart kPart =
          (KotlinClassMetadata.MultiFileClassPart) metadata;
      return new FoundKmPackageSubject(codeInspector, getDexProgramClass(), kPart.toKmPackage());
    }
  }

  @Override
  public KotlinClassMetadata getKotlinClassMetadata() {
    AnnotationSubject annotationSubject = annotation(METADATA_TYPE);
    if (!annotationSubject.isPresent()) {
      return null;
    }
    return KotlinClassMetadataReader.toKotlinClassMetadata(
        codeInspector.getFactory().kotlin, annotationSubject.getAnnotation());
  }

  public RetraceClassResult retrace() {
    assertTrue(mapping.getNaming() != null);
    return codeInspector
        .getRetracer()
        .retraceClass(Reference.classFromTypeName(mapping.getNaming().renamedName));
  }

  public RetraceClassElement retraceUnique() {
    RetraceClassResult result = retrace();
    if (result.isAmbiguous()) {
      fail("Expected unique retrace of " + this + ", got ambiguous: " + result);
    }
    Optional<RetraceClassElement> first = result.stream().findFirst();
    if (!first.isPresent()) {
      fail("Expected unique retrace of " + this + ", got empty result");
    }
    return first.get();
  }

  @Override
  public ClassNamingForNameMapper getNaming() {
    return mapping.getNaming();
  }

  @Override
  public String disassembleUsingJavap(boolean verbose) throws Exception {
    assert dexClass.origin != null;
    List<String> command = new ArrayList<>();
    command.add(
        CfRuntime.getCheckedInJdk9().getJavaHome().resolve("bin").resolve("javap").toString());
    if (verbose) {
      command.add("-v");
      command.add("-c");
      command.add("-p");
    }
    command.add("-cp");
    List<String> parts = dexClass.origin.parts();
    assert parts.size() == 2;
    command.add(parts.get(0));
    command.add(parts.get(1).replace(".class", ""));
    ProcessResult processResult = ToolHelper.runProcess(new ProcessBuilder(command));
    assert processResult.exitCode == 0;
    System.out.println(processResult.stdout);
    return processResult.stdout;
  }

  @Override
  public String asmify(TemporaryFolder tempFolder, boolean debug) throws Exception {
    assert dexClass.origin != null;
    List<String> parts = dexClass.origin.parts();
    assert parts.size() == 2;
    String directory = parts.get(0);
    String fileName = parts.get(1);
    if (directory.endsWith(".jar") || directory.endsWith(".zip")) {
      File tempOut = tempFolder.newFolder();
      ZipUtils.unzip(directory, tempOut);
      directory = tempOut.getAbsolutePath();
    }
    List<String> command = new ArrayList<>();
    command.add(
        CfRuntime.getCheckedInJdk9().getJavaHome().resolve("bin").resolve("java").toString());
    command.add("-cp");
    command.add(ToolHelper.ASM_JAR + ":" + ToolHelper.ASM_UTIL_JAR);
    command.add("org.objectweb.asm.util.ASMifier");
    if (!debug) {
      command.add("-debug");
    }
    command.add(Paths.get(directory, fileName).toString());
    ProcessResult processResult = ToolHelper.runProcess(new ProcessBuilder(command));
    assert processResult.exitCode == 0;
    System.out.println(processResult.stdout);
    return processResult.stdout;
  }
}
