// Copyright (c) 2018, the Dart 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.

/// Logic to expand and deobfuscate stack traces.

import 'package:stack_trace/stack_trace.dart';
import 'package:source_span/source_span.dart';
import 'package:source_maps/src/utils.dart';
import 'sourcemap_helper.dart';
import 'dart2js_mapping.dart';
import 'util.dart';

/// Provides the result of deobfuscating a stack trace.
class StackDeobfuscationResult {
  /// Representation of the obfuscated stack trace.
  final Trace original;

  /// Representation of the deobfuscated stack trace.
  final Trace deobfuscated;

  /// Details about how one original frame maps to deobfuscated frames. A single
  /// frame might map to many frames (in the case of inlining), or to a null
  /// value (when we were unable to deobfuscate it).
  final Map<Frame, List<Frame>> frameMap;

  StackDeobfuscationResult(this.original, this.deobfuscated, this.frameMap);
}

/// Parse [stackTrace] and deobfuscate it using source-map data available from
/// [provider].
StackDeobfuscationResult deobfuscateStack(
    String stackTrace, FileProvider provider) {
  var trace = Trace.parse(stackTrace.trim());
  var deobfuscatedFrames = <Frame>[];
  var frameMap = <Frame, List<Frame>>{};
  for (var frame in trace.frames) {
    var frameLine = frame.line;
    // If there's no line information, there's no way to translate this frame.
    // We could return it as-is, but these lines are usually not useful anyways.
    if (frameLine == null) {
      continue;
    }

    // If there's no column, try using the first column of the line.
    var column = frame.column ?? 1;

    Dart2jsMapping? mapping = provider.mappingFor(frame.uri);
    if (mapping == null) continue;

    // Subtract 1 because stack traces use 1-indexed lines and columns and
    // source maps uses 0-indexed.
    SourceSpan? span = mapping.sourceMap
        .spanFor(frameLine - 1, column - 1, uri: frame.uri.toString());

    // If we can't find a source span, ignore the frame. It's probably something
    // internal that the user doesn't care about.
    if (span == null) continue;

    List<Frame> mappedFrames = frameMap[frame] = [];

    SourceFile jsFile = provider.fileFor(frame.uri);
    int offset = jsFile.getOffset(frameLine - 1, column - 1);
    String nameOf(id) =>
        _normalizeName(id >= 0 ? mapping.sourceMap.names[id] : null);

    Uri? fileName = span.sourceUrl;
    int targetLine = span.start.line + 1;
    int targetColumn = span.start.column + 1;

    // Expand inlining data.  When present, the fileName, line and column above
    // correspond to the deepest inlined function, as we expand each frame we
    // consume the location information, and retrieve the location information
    // of the caller frame until we reach the actual function that dart2js
    // inlined all the code into.
    Map<int, List<FrameEntry>> frames = mapping.frames;
    List<int> index = mapping.frameIndex;
    int key = binarySearch(index, (i) => i > offset) - 1;
    int depth = 0;
    outer:
    while (key >= 0) {
      for (var frame in frames[index[key]]!.reversed) {
        if (frame.isEmpty) break outer;
        if (frame.isPush) {
          if (depth <= 0) {
            mappedFrames.add(new Frame(fileName!, targetLine, targetColumn,
                _normalizeName(frame.inlinedMethodName) + "(inlined)"));
            fileName = Uri.parse(frame.callUri!);
            targetLine = (frame.callLine ?? 0) + 1;
            targetColumn = (frame.callColumn ?? 0) + 1;
          } else {
            depth--;
          }
        }
        if (frame.isPop) {
          depth++;
        }
      }
      key--;
    }

    var functionEntry = findEnclosingFunction(provider, frame.uri, offset);
    String methodName = nameOf(functionEntry?.sourceNameId ?? -1);
    mappedFrames
        .add(new Frame(fileName!, targetLine, targetColumn, methodName));
    deobfuscatedFrames.addAll(mappedFrames);
  }
  return new StackDeobfuscationResult(
      trace, new Trace(deobfuscatedFrames), frameMap);
}

/// Ensure we don't use spaces in method names. At this time, they are only
/// introduced by `<anonymous function>`.
String _normalizeName(String? methodName) =>
    methodName?.replaceAll("<anonymous function>", "<anonymous>") ??
    '<unknown>';
