// 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.ir.desugar.InterfaceMethodRewriter.DEFAULT_METHOD_PREFIX;

import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfPosition;
import com.android.tools.r8.code.Instruction;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCode.LocalVariableInfo;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexDebugEvent;
import com.android.tools.r8.graph.DexDebugInfo;
import com.android.tools.r8.graph.DexDebugPositionState;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.naming.MemberNaming;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.signature.GenericSignatureParser;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.references.TypeReference;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.LocalVariableTable.LocalVariableTableEntry;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class FoundMethodSubject extends MethodSubject {

  private final CodeInspector codeInspector;
  private final FoundClassSubject clazz;
  private final DexEncodedMethod dexMethod;

  public FoundMethodSubject(
      CodeInspector codeInspector, DexEncodedMethod encoded, FoundClassSubject clazz) {
    this.codeInspector = codeInspector;
    this.clazz = clazz;
    this.dexMethod = encoded;
  }

  @Override
  public IRCode buildIR() {
    assert codeInspector.application.options.programConsumer != null;
    return getProgramMethod()
        .buildIR(AppView.createForD8(AppInfo.createInitialAppInfo(codeInspector.application)));
  }

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

  @Override
  public boolean isRenamed() {
    return clazz.naming != null && !getFinalSignature().name.equals(getOriginalSignature().name);
  }

  @Override
  public boolean isPublic() {
    return dexMethod.accessFlags.isPublic();
  }

  @Override
  public boolean isProtected() {
    return dexMethod.accessFlags.isProtected();
  }

  @Override
  public boolean isPrivate() {
    return dexMethod.accessFlags.isPrivate();
  }

  @Override
  public boolean isPackagePrivate() {
    return !isPublic() && !isProtected() && !isPrivate();
  }

  @Override
  public boolean isStatic() {
    return dexMethod.accessFlags.isStatic();
  }

  @Override
  public boolean isSynthetic() {
    return dexMethod.accessFlags.isSynthetic();
  }

  @Override
  public boolean isFinal() {
    return dexMethod.accessFlags.isFinal();
  }

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

  @Override
  public boolean isBridge() {
    return dexMethod.accessFlags.isBridge();
  }

  @Override
  public boolean isSynchronized() {
    return dexMethod.accessFlags.isSynchronized();
  }

  @Override
  public boolean isInstanceInitializer() {
    return dexMethod.isInstanceInitializer();
  }

  @Override
  public boolean isClassInitializer() {
    return dexMethod.isClassInitializer();
  }

  @Override
  public boolean isVirtual() {
    return dexMethod.isNonPrivateVirtualMethod();
  }

  @Override
  public DexEncodedMethod getMethod() {
    return dexMethod;
  }

  @Override
  public ProgramMethod getProgramMethod() {
    return new ProgramMethod(clazz.getDexProgramClass(), getMethod());
  }

  @Override
  public MethodSignature getOriginalSignature() {
    MethodSignature signature = getFinalSignature();
    if (clazz.naming == null) {
      return signature;
    }

    // Map the parameters and return type to original names. This is needed as the in the
    // Proguard map the names on the left side are the original names. E.g.
    //
    //   X -> a
    //     X method(X) -> a
    //
    // whereas the final signature is for X.a is "a (a)"
    String[] originalParameters = new String[signature.parameters.length];
    for (int i = 0; i < originalParameters.length; i++) {
      originalParameters[i] = codeInspector.getOriginalTypeName(signature.parameters[i]);
    }
    String returnType = codeInspector.getOriginalTypeName(signature.type);

    MethodSignature lookupSignature =
        new MethodSignature(signature.name, returnType, originalParameters);

    MemberNaming memberNaming = clazz.naming.lookup(lookupSignature);
    return memberNaming != null ? (MethodSignature) memberNaming.getOriginalSignature() : signature;
  }

  @Override
  public MethodSignature getFinalSignature() {
    return MethodSignature.fromDexMethod(dexMethod.method);
  }

  @Override
  public String getOriginalSignatureAttribute() {
    return codeInspector.getOriginalSignatureAttribute(
        dexMethod.annotations(), GenericSignatureParser::parseMethodSignature);
  }

  public DexMethod getOriginalDexMethod(DexItemFactory dexItemFactory) {
    MethodSignature methodSignature = getOriginalSignature();
    if (methodSignature.isQualified()) {
      methodSignature = methodSignature.toUnqualified();
    }
    return methodSignature.toDexMethod(
        dexItemFactory, dexItemFactory.createType(clazz.getOriginalDescriptor()));
  }

  @Override
  public String getFinalSignatureAttribute() {
    return codeInspector.getFinalSignatureAttribute(dexMethod.annotations());
  }

  public Iterable<InstructionSubject> instructions() {
    return instructions(Predicates.alwaysTrue());
  }

  public Iterable<InstructionSubject> instructions(Predicate<InstructionSubject> predicate) {
    return () -> iterateInstructions(predicate);
  }

  @Override
  public Iterator<InstructionSubject> iterateInstructions() {
    return codeInspector.createInstructionIterator(this);
  }

  @Override
  public <T extends InstructionSubject> Iterator<T> iterateInstructions(
      Predicate<InstructionSubject> filter) {
    return new FilteredInstructionIterator<>(codeInspector, this, filter);
  }

  @Override
  public Iterator<TryCatchSubject> iterateTryCatches() {
    return codeInspector.createTryCatchIterator(this);
  }

  @Override
  public <T extends TryCatchSubject> Iterator<T> iterateTryCatches(
      Predicate<TryCatchSubject> filter) {
    return new FilteredTryCatchIterator<>(codeInspector, this, filter);
  }

  @Override
  public boolean hasLocalVariableTable() {
    Code code = getMethod().getCode();
    if (code == null) {
      return false;
    }
    if (code.isDexCode()) {
      DexCode dexCode = code.asDexCode();
      if (dexCode.getDebugInfo() != null) {
        for (DexString parameter : dexCode.getDebugInfo().parameters) {
          if (parameter != null) {
            return true;
          }
        }
        for (DexDebugEvent event : dexCode.getDebugInfo().events) {
          if (event instanceof DexDebugEvent.StartLocal) {
            return true;
          }
        }
      }
      return false;
    }
    if (code.isCfCode()) {
      return !code.asCfCode().getLocalVariables().isEmpty();
    }
    throw new Unreachable("Unexpected code type: " + code.getClass().getSimpleName());
  }

  @Override
  public LineNumberTable getLineNumberTable() {
    Code code = getMethod().getCode();
    if (code == null) {
      return null;
    }
    if (code.isDexCode()) {
      return getDexLineNumberTable(code.asDexCode());
    }
    if (code.isCfCode()) {
      return getCfLineNumberTable(code.asCfCode());
    }
    throw new Unreachable("Unexpected code type: " + code.getClass().getSimpleName());
  }

  private LineNumberTable getCfLineNumberTable(CfCode code) {
    int currentLine = -1;
    Object2IntMap<InstructionSubject> lineNumberTable =
        new Object2IntOpenHashMap<>(code.getInstructions().size());
    for (CfInstruction insn : code.getInstructions()) {
      if (insn instanceof CfPosition) {
        currentLine = ((CfPosition) insn).getPosition().line;
      }
      if (currentLine != -1) {
        lineNumberTable.put(new CfInstructionSubject(insn, this), currentLine);
      }
    }
    return currentLine == -1 ? null : new LineNumberTable(lineNumberTable);
  }

  private LineNumberTable getDexLineNumberTable(DexCode code) {
    DexDebugInfo debugInfo = code.getDebugInfo();
    if (debugInfo == null) {
      return null;
    }
    Object2IntMap<InstructionSubject> lineNumberTable = new Object2IntOpenHashMap<>();
    DexDebugPositionState state =
        new DexDebugPositionState(debugInfo.startLine, getMethod().method);
    Iterator<DexDebugEvent> iterator = Arrays.asList(debugInfo.events).iterator();
    for (Instruction insn : code.instructions) {
      int offset = insn.getOffset();
      while (state.getCurrentPc() < offset && iterator.hasNext()) {
        iterator.next().accept(state);
      }
      lineNumberTable.put(new DexInstructionSubject(insn, this), state.getCurrentLine());
    }
    return new LineNumberTable(lineNumberTable);
  }

  @Override
  public LocalVariableTable getLocalVariableTable() {
    Code code = getMethod().getCode();
    if (code.isDexCode()) {
      return getDexLocalVariableTable(code.asDexCode());
    }
    if (code.isCfCode()) {
      return getCfLocalVariableTable(code.asCfCode());
    }
    throw new Unreachable("Unexpected code type: " + code.getClass().getSimpleName());
  }

  private LocalVariableTable getCfLocalVariableTable(CfCode code) {
    ImmutableList.Builder<LocalVariableTableEntry> builder = ImmutableList.builder();
    for (LocalVariableInfo localVariable : code.getLocalVariables()) {
      builder.add(
          new LocalVariableTableEntry(
              localVariable.getIndex(),
              localVariable.getLocal().name.toString(),
              new TypeSubject(codeInspector, localVariable.getLocal().type),
              localVariable.getLocal().signature == null
                  ? null
                  : localVariable.getLocal().signature.toString(),
              new CfInstructionSubject(localVariable.getStart(), this),
              new CfInstructionSubject(localVariable.getEnd(), this)));
    }
    return new LocalVariableTable(builder.build());
  }

  private LocalVariableTable getDexLocalVariableTable(DexCode code) {
    throw new Unimplemented("No support for inspecting the line number table for DexCode");
  }

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

  @Override
  public AnnotationSubject annotation(String name) {
    DexAnnotation annotation = codeInspector.findAnnotation(name, dexMethod.annotations());
    return annotation == null
        ? new AbsentAnnotationSubject()
        : new FoundAnnotationSubject(annotation);
  }

  @Override
  public FoundMethodSubject asFoundMethodSubject() {
    return this;
  }

  public MethodReference asMethodReference() {
    DexMethod method = dexMethod.method;
    return Reference.method(
        Reference.classFromDescriptor(method.holder.toDescriptorString()),
        method.name.toString(),
        Arrays.stream(method.proto.parameters.values)
            .map(type -> Reference.typeFromDescriptor(type.toDescriptorString()))
            .collect(Collectors.toList()),
        Reference.returnTypeFromDescriptor(method.proto.returnType.toDescriptorString()));
  }

  @Override
  public String getJvmMethodSignatureAsString() {
    return dexMethod.method.name.toString()
        + "("
        + StringUtils.join(
            Arrays.stream(dexMethod.method.proto.parameters.values)
                .map(DexType::toDescriptorString).collect(Collectors.toList()), "")
        + ")"
        + dexMethod.method.proto.returnType.toDescriptorString();
  }

  @Override
  public MethodSubject toMethodOnCompanionClass() {
    ClassSubject companionClass = clazz.toCompanionClass();
    MethodReference reference = asMethodReference();
    List<String> p =
        ImmutableList.<String>builder()
            .add(clazz.getFinalName())
            .addAll(reference.getFormalTypes().stream().map(TypeReference::getTypeName).iterator())
            .build();
    return companionClass.method(
        reference.getReturnType().getTypeName(),
        DEFAULT_METHOD_PREFIX + reference.getMethodName(),
        p);
  }
}
