// 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.retrace.internal;

import static com.android.tools.r8.retrace.internal.RetraceUtils.methodReferenceFromMappedRange;

import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
import com.android.tools.r8.naming.MemberNaming;
import com.android.tools.r8.naming.Range;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.retrace.RetraceFrameElement;
import com.android.tools.r8.retrace.RetraceFrameResult;
import com.android.tools.r8.retrace.RetraceInvalidRewriteFrameDiagnostics;
import com.android.tools.r8.retrace.RetraceStackTraceContext;
import com.android.tools.r8.retrace.RetracedClassMemberReference;
import com.android.tools.r8.retrace.RetracedSingleFrame;
import com.android.tools.r8.retrace.RetracedSourceFile;
import com.android.tools.r8.retrace.internal.RetraceClassResultImpl.RetraceClassElementImpl;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.OptionalUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.function.Consumer;
import java.util.stream.Stream;

class RetraceFrameResultImpl implements RetraceFrameResult {

  private final RetraceClassResultImpl classResult;
  private final MethodDefinition methodDefinition;
  private final List<RetraceFrameResultData> mappedRanges;
  private final RetracerImpl retracer;
  private final RetraceStackTraceContextImpl context;

  private OptionalBool isAmbiguousCache = OptionalBool.UNKNOWN;

  public RetraceFrameResultImpl(
      RetraceClassResultImpl classResult,
      List<RetraceFrameResultData> mappedRanges,
      MethodDefinition methodDefinition,
      RetracerImpl retracer,
      RetraceStackTraceContextImpl context) {
    this.classResult = classResult;
    this.methodDefinition = methodDefinition;
    this.mappedRanges = mappedRanges;
    this.retracer = retracer;
    this.context = context;
    assert !mappedRanges.isEmpty();
  }

  @Override
  public boolean isAmbiguous() {
    if (isAmbiguousCache.isUnknown()) {
      isAmbiguousCache = OptionalBool.of(computeIsAmbiguous());
      assert !isAmbiguousCache.isUnknown();
    }
    return isAmbiguousCache.isTrue();
  }

  private boolean computeIsAmbiguous() {
    if (mappedRanges.size() > 1) {
      return true;
    }
    return mappedRanges.get(0).isAmbiguous();
  }

  private boolean isMappedRangeAmbiguous(MappedRange mappedRange) {
    if (mappedRange.originalRange == null || mappedRange.originalRange.span() == 1) {
      // If there is no original position or all maps to a single position, the result is not
      // ambiguous.
      return false;
    }
    return mappedRange.minifiedRange == null
        || mappedRange.minifiedRange.span() != mappedRange.originalRange.span();
  }

  @Override
  public Stream<RetraceFrameElement> stream() {
    return mappedRanges.stream()
        .flatMap(
            mappedRangeData -> {
              RetraceClassElementImpl classElement = mappedRangeData.getRetraceClassElement();
              List<MemberNamingWithMappedRangesOfName> memberNamingWithMappedRangesOfNames =
                  mappedRangeData.getMemberNamingWithMappedRanges();
              if (memberNamingWithMappedRangesOfNames == null
                  || memberNamingWithMappedRangesOfNames.isEmpty()) {
                return Stream.of(
                    new ElementImpl(
                        this,
                        classElement,
                        RetracedMethodReferenceImpl.create(
                            methodDefinition.substituteHolder(
                                classElement.getRetracedClass().getClassReference())),
                        ImmutableList.of(),
                        Optional.empty(),
                        mappedRangeData.getPosition(),
                        retracer));
              }
              // Iterate over mapped ranges that may have different positions than specified.
              List<ElementImpl> ambiguousFrames = new ArrayList<>();
              for (MemberNamingWithMappedRangesOfName memberNamingWithMappedRangesOfName :
                  memberNamingWithMappedRangesOfNames) {
                List<MappedRange> mappedRangesForMemberNaming =
                    memberNamingWithMappedRangesOfName.getMappedRanges();
                MappedRange firstMappedRange = mappedRangesForMemberNaming.get(0);
                Range minifiedRange = firstMappedRange.minifiedRange;
                List<MappedRange> mappedRangesForElement = Lists.newArrayList(firstMappedRange);
                for (int i = 1; i < mappedRangesForMemberNaming.size(); i++) {
                  MappedRange mappedRange = mappedRangesForMemberNaming.get(i);
                  if (minifiedRange == null || !minifiedRange.equals(mappedRange.minifiedRange)) {
                    // This is a new frame
                    separateAmbiguousOriginalPositions(
                        classElement,
                        Optional.ofNullable(memberNamingWithMappedRangesOfName.getMemberNaming()),
                        mappedRangesForElement,
                        ambiguousFrames,
                        mappedRangeData.getPosition());
                    mappedRangesForElement = new ArrayList<>();
                    minifiedRange = mappedRange.minifiedRange;
                  }
                  mappedRangesForElement.add(mappedRange);
                }
                separateAmbiguousOriginalPositions(
                    classElement,
                    Optional.ofNullable(memberNamingWithMappedRangesOfName.getMemberNaming()),
                    mappedRangesForElement,
                    ambiguousFrames,
                    mappedRangeData.getPosition());
              }
              return ambiguousFrames.stream();
            });
  }

  private void separateAmbiguousOriginalPositions(
      RetraceClassElementImpl classElement,
      Optional<MemberNaming> memberNaming,
      List<MappedRange> frames,
      List<ElementImpl> allAmbiguousElements,
      OptionalInt obfuscatedPosition) {
    // We have a single list of frames where minified positional information may produce ambiguous
    // results.
    if (!isAmbiguous() || !isMappedRangeAmbiguous(frames.get(0))) {
      allAmbiguousElements.add(
          elementFromMappedRanges(
              ListUtils.map(frames, MappedRangeForFrame::create),
              memberNaming,
              classElement,
              obfuscatedPosition));
      return;
    }
    assert frames.size() > 0;
    assert frames.get(0).originalRange != null
        && frames.get(0).originalRange.to > frames.get(0).originalRange.from;
    List<List<MappedRangeForFrame>> newFrames = new ArrayList<>();
    ListUtils.forEachWithIndex(
        frames,
        (frame, index) -> {
          // Only the top inline can give rise to ambiguity since the remaining inline frames will
          // have a single line number.
          if (index == 0) {
            for (int i = frame.originalRange.from; i <= frame.originalRange.to; i++) {
              List<MappedRangeForFrame> ambiguousFrames = new ArrayList<>();
              ambiguousFrames.add(MappedRangeForFrame.create(frame, OptionalInt.of(i)));
              newFrames.add(ambiguousFrames);
            }
          } else {
            newFrames.forEach(
                ambiguousFrames -> ambiguousFrames.add(MappedRangeForFrame.create(frame)));
          }
        });
    newFrames.forEach(
        ambiguousFrames ->
            allAmbiguousElements.add(
                elementFromMappedRanges(
                    ambiguousFrames, memberNaming, classElement, obfuscatedPosition)));
  }

  private ElementImpl elementFromMappedRanges(
      List<MappedRangeForFrame> mappedRangesForElement,
      Optional<MemberNaming> memberNaming,
      RetraceClassElementImpl classElement,
      OptionalInt obfuscatedPosition) {
    MappedRangeForFrame topFrame = mappedRangesForElement.get(0);
    MethodReference methodReference =
        methodReferenceFromMappedRange(
            topFrame.mappedRange, classElement.getRetracedClass().getClassReference());
    return new ElementImpl(
        this,
        classElement,
        getRetracedMethod(methodReference, topFrame, obfuscatedPosition),
        mappedRangesForElement,
        memberNaming,
        obfuscatedPosition,
        retracer);
  }

  private RetracedMethodReferenceImpl getRetracedMethod(
      MethodReference methodReference,
      MappedRangeForFrame mappedRangeForFrame,
      OptionalInt obfuscatedPosition) {
    MappedRange mappedRange = mappedRangeForFrame.mappedRange;
    OptionalInt originalPosition = mappedRangeForFrame.position;
    if (!isAmbiguous()
        && (mappedRange.minifiedRange == null || obfuscatedPosition.orElse(-1) == -1)) {
      int originalLineNumber = mappedRange.getFirstPositionOfOriginalRange(0);
      if (originalLineNumber > 0) {
        return RetracedMethodReferenceImpl.create(
            methodReference, OptionalUtils.orElse(originalPosition, originalLineNumber));
      } else {
        return RetracedMethodReferenceImpl.create(methodReference, originalPosition);
      }
    }
    if (!obfuscatedPosition.isPresent()
        || mappedRange.minifiedRange == null
        || !mappedRange.minifiedRange.contains(obfuscatedPosition.getAsInt())) {
      return RetracedMethodReferenceImpl.create(methodReference, originalPosition);
    }
    return RetracedMethodReferenceImpl.create(
        methodReference,
        OptionalUtils.orElseGet(
            originalPosition,
            () -> mappedRange.getOriginalLineNumber(obfuscatedPosition.getAsInt())));
  }

  @Override
  public boolean isEmpty() {
    List<MemberNamingWithMappedRangesOfName> mappedRangesOfNames =
        mappedRanges.get(0).getMemberNamingWithMappedRanges();
    return mappedRangesOfNames == null || mappedRangesOfNames.isEmpty();
  }

  public static class ElementImpl implements RetraceFrameElement {

    private final RetracedMethodReferenceImpl methodReference;
    private final RetraceFrameResultImpl retraceFrameResult;
    private final RetraceClassElementImpl classElement;
    private final List<MappedRangeForFrame> mappedRanges;
    private final Optional<MemberNaming> memberNaming;
    private final OptionalInt obfuscatedPosition;
    private final RetracerImpl retracer;

    ElementImpl(
        RetraceFrameResultImpl retraceFrameResult,
        RetraceClassElementImpl classElement,
        RetracedMethodReferenceImpl methodReference,
        List<MappedRangeForFrame> mappedRanges,
        Optional<MemberNaming> memberNaming,
        OptionalInt obfuscatedPosition,
        RetracerImpl retracer) {
      this.methodReference = methodReference;
      this.retraceFrameResult = retraceFrameResult;
      this.classElement = classElement;
      this.mappedRanges = mappedRanges;
      this.memberNaming = memberNaming;
      this.obfuscatedPosition = obfuscatedPosition;
      this.retracer = retracer;
    }

    private boolean isOuterMostFrameCompilerSynthesized() {
      if (memberNaming.isPresent()) {
        return memberNaming.get().isCompilerSynthesized();
      }
      if (mappedRanges == null || mappedRanges.isEmpty()) {
        return false;
      }
      return ListUtils.last(mappedRanges).mappedRange.isCompilerSynthesized();
    }

    /**
     * Predicate determines if the *entire* frame is to be considered synthetic.
     *
     * <p>That is only true for a frame that has just one entry and that entry is synthetic.
     */
    @Override
    public boolean isCompilerSynthesized() {
      return getOuterFrames().isEmpty() && isOuterMostFrameCompilerSynthesized();
    }

    @Override
    public RetraceFrameResult getParentResult() {
      return retraceFrameResult;
    }

    @Override
    public boolean isUnknown() {
      return methodReference.isUnknown();
    }

    @Override
    public RetracedMethodReferenceImpl getTopFrame() {
      return methodReference;
    }

    @Override
    public RetraceClassElementImpl getClassElement() {
      return classElement;
    }

    @Override
    public void forEach(Consumer<RetracedSingleFrame> consumer) {
      if (mappedRanges == null || mappedRanges.isEmpty()) {
        consumer.accept(RetracedSingleFrameImpl.create(this, getTopFrame(), 0));
        return;
      }
      int counter = 0;
      consumer.accept(RetracedSingleFrameImpl.create(this, getTopFrame(), counter++));
      for (RetracedMethodReferenceImpl outerFrame : getOuterFrames()) {
        consumer.accept(RetracedSingleFrameImpl.create(this, outerFrame, counter++));
      }
    }

    @Override
    public Stream<RetracedSingleFrame> stream() {
      Stream.Builder<RetracedSingleFrame> builder = Stream.builder();
      forEach(builder::add);
      return builder.build();
    }

    @Override
    public void forEachRewritten(Consumer<RetracedSingleFrame> consumer) {
      RetraceStackTraceContextImpl contextImpl = retraceFrameResult.context;
      RetraceStackTraceCurrentEvaluationInformation currentFrameInformation =
          contextImpl == null
              ? RetraceStackTraceCurrentEvaluationInformation.empty()
              : contextImpl.computeRewriteFrameInformation(
                  ListUtils.map(mappedRanges, MappedRangeForFrame::getMappedRange));
      int index = 0;
      int numberOfFramesToRemove = currentFrameInformation.getRemoveInnerFramesCount();
      int totalNumberOfFrames =
          (mappedRanges == null || mappedRanges.isEmpty()) ? 1 : mappedRanges.size();
      if (numberOfFramesToRemove > totalNumberOfFrames) {
        DiagnosticsHandler diagnosticsHandler = retracer.getDiagnosticsHandler();
        diagnosticsHandler.warning(
            RetraceInvalidRewriteFrameDiagnostics.create(
                numberOfFramesToRemove, getTopFrame().asKnown().toString()));
        numberOfFramesToRemove = 0;
      }
      RetracedMethodReferenceImpl prev = getTopFrame();
      List<RetracedMethodReferenceImpl> outerFrames = getOuterFrames();
      for (RetracedMethodReferenceImpl next : outerFrames) {
        if (numberOfFramesToRemove-- <= 0) {
          consumer.accept(RetracedSingleFrameImpl.create(this, prev, index++));
        }
        prev = next;
      }
      // We expect only the last frame, i.e., the outer-most caller to potentially be synthesized.
      // If not include it too.
      if (numberOfFramesToRemove <= 0 && !isOuterMostFrameCompilerSynthesized()) {
        consumer.accept(RetracedSingleFrameImpl.create(this, prev, index));
      }
    }

    @Override
    public Stream<RetracedSingleFrame> streamRewritten(RetraceStackTraceContext context) {
      Stream.Builder<RetracedSingleFrame> builder = Stream.builder();
      forEachRewritten(builder::add);
      return builder.build();
    }

    @Override
    public RetracedSourceFile getSourceFile(RetracedClassMemberReference frame) {
      return RetraceUtils.getSourceFile(frame.getHolderClass(), retraceFrameResult.retracer);
    }

    @Override
    public List<RetracedMethodReferenceImpl> getOuterFrames() {
      if (mappedRanges == null) {
        return Collections.emptyList();
      }
      List<RetracedMethodReferenceImpl> outerFrames = new ArrayList<>();
      for (int i = 1; i < mappedRanges.size(); i++) {
        outerFrames.add(getMethodReferenceFromMappedRange(mappedRanges.get(i)));
      }
      return outerFrames;
    }

    private RetracedMethodReferenceImpl getMethodReferenceFromMappedRange(
        MappedRangeForFrame mappedRangeForFrame) {
      MethodReference methodReference =
          methodReferenceFromMappedRange(
              mappedRangeForFrame.getMappedRange(),
              classElement.getRetracedClass().getClassReference());
      return retraceFrameResult.getRetracedMethod(
          methodReference, mappedRangeForFrame, obfuscatedPosition);
    }

    @Override
    public RetraceStackTraceContext getRetraceStackTraceContext() {
      if (mappedRanges == null
          || mappedRanges.isEmpty()
          || !obfuscatedPosition.isPresent()
          || !isOutlineFrame()) {
        return RetraceStackTraceContext.empty();
      }
      return RetraceStackTraceContextImpl.builder().setRewritePosition(obfuscatedPosition).build();
    }

    private boolean isOutlineFrame() {
      if (memberNaming.isPresent()) {
        return memberNaming.get().isOutlineFrame();
      }
      if (mappedRanges == null || mappedRanges.isEmpty()) {
        return false;
      }
      return ListUtils.last(mappedRanges).getMappedRange().isOutlineFrame();
    }
  }

  private static class MappedRangeForFrame {

    private final MappedRange mappedRange;
    private final OptionalInt position;

    private MappedRangeForFrame(MappedRange mappedRange, OptionalInt position) {
      this.mappedRange = mappedRange;
      this.position = position;
    }

    private MappedRange getMappedRange() {
      return mappedRange;
    }

    private static MappedRangeForFrame create(MappedRange mappedRange) {
      return create(
          mappedRange,
          mappedRange.originalRange == null || mappedRange.originalRange.span() != 1
              ? OptionalInt.empty()
              : OptionalInt.of(mappedRange.originalRange.from));
    }

    private static MappedRangeForFrame create(MappedRange mappedRange, OptionalInt position) {
      return new MappedRangeForFrame(mappedRange, position);
    }
  }
}
