// Copyright (c) 2019, 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.

import 'dart:async';

import 'package:dwds/src/config/tool_configuration.dart';
import 'package:dwds/src/debugging/dart_scope.dart';
import 'package:dwds/src/debugging/frame_computer.dart';
import 'package:dwds/src/debugging/location.dart';
import 'package:dwds/src/debugging/remote_debugger.dart';
import 'package:dwds/src/debugging/skip_list.dart';
import 'package:dwds/src/services/chrome_debug_exception.dart';
import 'package:dwds/src/utilities/dart_uri.dart';
import 'package:dwds/src/utilities/domain.dart';
import 'package:dwds/src/utilities/objects.dart' show Property;
import 'package:dwds/src/utilities/server.dart';
import 'package:dwds/src/utilities/shared.dart';
import 'package:dwds/src/utilities/synchronized.dart';
import 'package:logging/logging.dart';
import 'package:vm_service/vm_service.dart';
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
    hide StackTrace;

/// Adds [event] to the stream with [streamId] if there is anybody listening
/// on that stream.
typedef StreamNotify = void Function(String streamId, Event event);

/// Converts from ExceptionPauseMode strings to [PauseState] enums.
///
/// Values defined in:
/// https://chromedevtools.github.io/devtools-protocol/tot/Debugger#method-setPauseOnExceptions
const _pauseModePauseStates = {
  'none': PauseState.none,
  'all': PauseState.all,
  'unhandled': PauseState.uncaught,
};

class Debugger extends Domain {
  static final logger = Logger('Debugger');

  final RemoteDebugger _remoteDebugger;

  final StreamNotify _streamNotify;
  final Locations _locations;
  final SkipLists _skipLists;
  final String _root;

  Debugger._(
    this._remoteDebugger,
    this._streamNotify,
    this._locations,
    this._skipLists,
    this._root,
  ) : _breakpoints = _Breakpoints(
          locations: _locations,
          remoteDebugger: _remoteDebugger,
          root: _root,
        );

  /// The breakpoints we have set so far, indexable by either
  /// Dart or JS ID.
  final _Breakpoints _breakpoints;

  PauseState _pauseState = PauseState.none;

  // TODO(elliette): https://github.com/dart-lang/webdev/issues/1501 Re-enable
  // after checking with Chrome team if there is a way to check if the Chrome
  // DevTools is showing an overlay. Both cannot be shown at the same time:
  // bool _pausedOverlayVisible = false;

  String get pauseState => _pauseModePauseStates.entries
      .firstWhere((entry) => entry.value == _pauseState)
      .key;

  /// The JS frames at the current paused location.
  ///
  /// The most important thing here is that frames are identified by
  /// frameIndex in the Dart API, but by frame Id in Chrome, so we need
  /// to keep the JS frames and their Ids around.
  FrameComputer? stackComputer;

  bool _isStepping = false;
  DartLocation? _previousSteppingLocation;

  void updateInspector(AppInspectorInterface appInspector) {
    inspector = appInspector;
    _breakpoints.inspector = appInspector;
  }

  Future<Success> pause() async {
    _isStepping = false;
    final result = await _remoteDebugger.pause();
    handleErrorIfPresent(result);
    return Success();
  }

  Future<Success> setExceptionPauseMode(String mode) async {
    mode = mode.toLowerCase();
    final state = _pauseModePauseStates[mode];
    if (state == null) {
      throwInvalidParam('setExceptionPauseMode', 'Unsupported mode: $mode');
    } else {
      _pauseState = state;
    }
    await _remoteDebugger.setPauseOnExceptions(_pauseState);
    return Success();
  }

  /// Resumes the debugger.
  ///
  /// Step parameter options:
  /// https://github.com/dart-lang/sdk/blob/main/runtime/vm/service/service.md#resume
  ///
  /// If the step parameter is not provided, the program will resume regular
  /// execution.
  ///
  /// If the step parameter is provided, it indicates what form of
  /// single-stepping to use.
  ///
  /// Note that stepping will automatically continue until Chrome is paused at
  /// a location for which we have source information.
  Future<Success> resume({String? step, int? frameIndex}) async {
    try {
      if (frameIndex != null) {
        throw ArgumentError('FrameIndex is currently unsupported.');
      }
      WipResponse? result;
      if (step != null) {
        _isStepping = true;
        switch (step) {
          case 'Over':
            result = await _remoteDebugger.stepOver();
            break;
          case 'Out':
            result = await _remoteDebugger.stepOut();
            break;
          case 'Into':
            result = await _remoteDebugger.stepInto();
            break;
          default:
            throwInvalidParam('resume', 'Unexpected value for step: $step');
        }
      } else {
        _isStepping = false;
        _previousSteppingLocation = null;
        result = await _remoteDebugger.resume();
      }
      handleErrorIfPresent(result);
      return Success();
    } on WipError catch (e) {
      final errorMessage = e.message;
      if (errorMessage != null &&
          errorMessage.contains('Can only perform operation while paused')) {
        throw RPCError(
          'resume',
          RPCErrorKind.kIsolateMustBePaused.code,
          errorMessage,
        );
      }
      rethrow;
    }
  }

  /// Returns the current Dart stack for the paused debugger.
  ///
  /// Throws RPCError if the debugger is not paused.
  ///
  /// The returned stack will contain up to [limit] frames if provided.
  Future<Stack> getStack({int? limit}) async {
    if (stackComputer == null) {
      throw RPCError(
        'getStack',
        RPCErrorKind.kInternalError.code,
        'Cannot compute stack when application is not paused',
      );
    }

    final frames = await stackComputer!.calculateFrames(limit: limit);
    return Stack(
      frames: frames,
      messages: [],
      truncated: limit != null && frames.length == limit,
    );
  }

  static Future<Debugger> create(
    RemoteDebugger remoteDebugger,
    StreamNotify streamNotify,
    Locations locations,
    SkipLists skipLists,
    String root,
  ) async {
    final debugger = Debugger._(
      remoteDebugger,
      streamNotify,
      locations,
      skipLists,
      root,
    );
    await debugger._initialize();
    return debugger;
  }

  Future<void> _initialize() async {
    // We must add a listener before enabling the debugger otherwise we will
    // miss events.
    // Allow a null debugger/connection for unit tests.
    runZonedGuarded(() {
      _remoteDebugger.onPaused.listen(_pauseHandler);
      _remoteDebugger.onResumed.listen(_resumeHandler);
      _remoteDebugger.onTargetCrashed.listen(_crashHandler);
    }, (e, StackTrace s) {
      logger.warning('Error handling Chrome event', e, s);
    });

    handleErrorIfPresent(await _remoteDebugger.enablePage());
    await _remoteDebugger.enable();

    // Enable collecting information about async frames when paused.
    handleErrorIfPresent(
      await _remoteDebugger.sendCommand(
        'Debugger.setAsyncCallStackDepth',
        params: {
          'maxDepth': 128,
        },
      ),
    );
  }

  /// Resumes the Isolate from start.
  ///
  /// The JS VM is technically not paused at the start of the Isolate so there
  /// will not be a corresponding [DebuggerResumedEvent].
  void resumeFromStart() => _resumeHandler(null);

  /// Notify the debugger the [Isolate] is paused at the application start.
  void notifyPausedAtStart() {
    stackComputer = FrameComputer(this, []);
  }

  /// Add a breakpoint at the given position.
  ///
  /// Note that line and column are Dart source locations and are one-based.
  Future<Breakpoint> addBreakpoint(
    String scriptId,
    int line, {
    int? column,
  }) async {
    column ??= 0;
    final breakpoint = await _breakpoints.add(scriptId, line, column);
    _notifyBreakpoint(breakpoint);
    return breakpoint;
  }

  Future<ScriptRef?> _updatedScriptRefFor(Breakpoint breakpoint) async {
    final oldRef = (breakpoint.location as SourceLocation).script;
    final uri = oldRef?.uri;
    if (uri == null) return null;
    final dartUri = DartUri(uri, _root);
    return await inspector.scriptRefFor(dartUri.serverPath);
  }

  Future<void> reestablishBreakpoints(
    Set<Breakpoint> previousBreakpoints,
    Set<Breakpoint> disabledBreakpoints,
  ) async {
    // Previous breakpoints were never removed from Chrome since we use
    // `setBreakpointByUrl`. We simply need to update the references.
    for (var breakpoint in previousBreakpoints) {
      final dartBpId = breakpoint.id!;
      final scriptRef = await _updatedScriptRefFor(breakpoint);
      final scriptUri = scriptRef?.uri;
      if (scriptRef != null && scriptUri != null) {
        final jsBpId = _breakpoints.jsIdFor(dartBpId)!;
        final updatedLocation = await _locations.locationForDart(
          DartUri(scriptUri, _root),
          _lineNumberFor(breakpoint),
          _columnNumberFor(breakpoint),
        );
        if (updatedLocation != null) {
          final updatedBreakpoint = _breakpoints._dartBreakpoint(
            scriptRef,
            updatedLocation,
            dartBpId,
          );
          _breakpoints._note(bp: updatedBreakpoint, jsId: jsBpId);
          _notifyBreakpoint(updatedBreakpoint);
        } else {
          logger.warning('Cannot update breakpoint $dartBpId:'
              ' cannot update location.');
        }
      } else {
        logger.warning('Cannot update breakpoint $dartBpId:'
            ' cannot find script ref.');
      }
    }

    // Disabled breakpoints were actually removed from Chrome so simply add
    // them back.
    for (var breakpoint in disabledBreakpoints) {
      final scriptRef = await _updatedScriptRefFor(breakpoint);
      final scriptId = scriptRef?.id;
      if (scriptId != null) {
        await addBreakpoint(
          scriptId,
          _lineNumberFor(breakpoint),
          column: _columnNumberFor(breakpoint),
        );
      } else {
        logger.warning('Cannot update disabled breakpoint ${breakpoint.id}:'
            ' cannot find script ref.');
      }
    }
  }

  void _notifyBreakpoint(Breakpoint breakpoint) {
    final event = Event(
      kind: EventKind.kBreakpointAdded,
      timestamp: DateTime.now().millisecondsSinceEpoch,
      isolate: inspector.isolateRef,
    );
    event.breakpoint = breakpoint;
    _streamNotify('Debug', event);
  }

  /// Remove a Dart breakpoint.
  Future<Success> removeBreakpoint(String breakpointId) async {
    if (_breakpoints.breakpointFor(breakpointId) == null) {
      throwInvalidParam(
        'removeBreakpoint',
        'invalid breakpoint id $breakpointId',
      );
    }
    final jsId = _breakpoints.jsIdFor(breakpointId);
    if (jsId == null) {
      throw RPCError(
        'removeBreakpoint',
        RPCErrorKind.kInternalError.code,
        'invalid JS breakpoint id $jsId',
      );
    }
    await _removeBreakpoint(jsId);

    final bp = await _breakpoints.remove(jsId: jsId, dartId: breakpointId);
    if (bp != null) {
      _streamNotify(
        'Debug',
        Event(
          kind: EventKind.kBreakpointRemoved,
          timestamp: DateTime.now().millisecondsSinceEpoch,
          isolate: inspector.isolateRef,
        )..breakpoint = bp,
      );
    }
    return Success();
  }

  /// Call the Chrome protocol removeBreakpoint.
  Future<void> _removeBreakpoint(String breakpointId) async {
    try {
      final response = await _remoteDebugger.removeBreakpoint(breakpointId);
      handleErrorIfPresent(response);
    } on WipError catch (e) {
      throw RPCError('removeBreakpoint', 102, '$e');
    }
  }

  /// Returns Chrome script uri for Chrome script ID.
  String? urlForScriptId(String scriptId) =>
      _remoteDebugger.scripts[scriptId]?.url;

  /// Returns source [Location] for the paused event.
  ///
  /// If we do not have [Location] data for the embedded JS location, null is
  /// returned.
  Future<Location?> _sourceLocation(DebuggerPausedEvent e) async {
    final frame = e.params?['callFrames']?[0];
    final location = frame?['location'];
    if (location == null) return null;

    final scriptId = location['scriptId'] as String?;
    final line = location['lineNumber'] as int?;
    if (scriptId == null || line == null) return null;

    final column = location['columnNumber'] as int?;
    final url = urlForScriptId(scriptId);
    if (url == null) return null;

    final loc = await _locations.locationForJs(url, line, column);
    if (loc == null || loc.dartLocation == _previousSteppingLocation) {
      return null;
    }
    _previousSteppingLocation = loc.dartLocation;
    return loc;
  }

  /// Returns script ID for the paused event.
  String? _frameScriptId(DebuggerPausedEvent e) {
    final frame = e.params?['callFrames']?[0];
    return frame?['location']?['scriptId'] as String?;
  }

  /// The variables visible in a frame in Dart protocol [BoundVariable] form.
  Future<List<BoundVariable>> variablesFor(WipCallFrame frame) async {
    // TODO(alanknight): Can these be moved to dart_scope.dart?
    final properties =
        await visibleVariables(inspector: inspector, frame: frame);
    final boundVariables = await Future.wait(
      properties.map(_boundVariable),
    );

    // Filter out variables that do not come from dart code, such as native
    // JavaScript objects
    return boundVariables
        .where((bv) => inspector.isDisplayableObject(bv?.value))
        .toList()
        .cast();
  }

  Future<BoundVariable?> _boundVariable(Property property) async {
    // TODO(annagrin): value might be null in the future for variables
    // optimized by V8. Return appropriate sentinel values for them.
    if (property.value != null) {
      final value = property.value!;
      // We return one level of properties from this object. Sub-properties are
      // another round trip.
      final instanceRef = await inspector.instanceRefFor(value);
      // Skip null instance refs, which we get for weird objects, e.g.
      // properties that are getter/setter pairs.
      // TODO(alanknight): Handle these properly.
      if (instanceRef == null) return null;

      return BoundVariable(
        name: property.name,
        value: instanceRef,
        // TODO(grouma) - Provide actual token positions.
        declarationTokenPos: -1,
        scopeStartTokenPos: -1,
        scopeEndTokenPos: -1,
      );
    }
    return null;
  }

  // TODO(elliette): https://github.com/dart-lang/webdev/issues/1501 Re-enable
  // after checking with Chrome team if there is a way to check if the Chrome
  // DevTools is showing an overlay. Both cannot be shown at the same time:

  // Renders the paused at breakpoint overlay over the application.
  // void _showPausedOverlay() async {
  //   if (_pausedOverlayVisible) return;
  //   handleErrorIfPresent(await _remoteDebugger?.sendCommand('DOM.enable'));
  //   handleErrorIfPresent(await _remoteDebugger?.sendCommand('Overlay.enable'));
  //   handleErrorIfPresent(await _remoteDebugger
  //       ?.sendCommand('Overlay.setPausedInDebuggerMessage', params: {
  //     'message': 'Paused',
  //   }));
  //   _pausedOverlayVisible = true;
  // }

  // Removes the paused at breakpoint overlay from the application.
  // void _hidePausedOverlay() async {
  //   if (!_pausedOverlayVisible) return;
  //   handleErrorIfPresent(await _remoteDebugger?.sendCommand('Overlay.disable'));
  //   _pausedOverlayVisible = false;
  // }

  /// Returns a Dart [Frame] for a JS [frame].
  Future<Frame?> calculateDartFrameFor(
    WipCallFrame frame,
    int frameIndex, {
    bool populateVariables = true,
  }) async {
    final location = frame.location;
    final line = location.lineNumber;
    final column = location.columnNumber;

    final url = urlForScriptId(location.scriptId);
    if (url == null) {
      logger.fine('Failed to create dart frame for ${frame.functionName}: '
          'cannot find url for script ${location.scriptId}');
      return null;
    }

    final bestLocation = await _locations.locationForJs(url, line, column ?? 0);
    if (bestLocation == null) return null;

    final script =
        await inspector.scriptRefFor(bestLocation.dartLocation.uri.serverPath);
    // We think we found a location, but for some reason we can't find the
    // script. Just drop the frame.
    // TODO(#700): Understand when this can happen and have a better fix.
    if (script == null) return null;

    final functionName = _prettifyMember((frame.functionName).split('.').last);
    final codeRefName = functionName.isEmpty ? '<closure>' : functionName;

    final dartFrame = Frame(
      index: frameIndex,
      code: CodeRef(
        name: codeRefName,
        kind: CodeKind.kDart,
        id: createId(),
      ),
      location: SourceLocation(
        line: bestLocation.dartLocation.line,
        column: bestLocation.dartLocation.column,
        tokenPos: bestLocation.tokenPos,
        script: script,
      ),
      kind: FrameKind.kRegular,
    );

    // Don't populate variables for async frames.
    if (populateVariables) {
      dartFrame.vars = await variablesFor(frame);
    }

    return dartFrame;
  }

  /// Handles pause events coming from the Chrome connection.
  Future<void> _pauseHandler(DebuggerPausedEvent e) async {
    final isolate = inspector.isolate;
    Event event;
    final timestamp = DateTime.now().millisecondsSinceEpoch;
    final jsBreakpointIds = e.hitBreakpoints ?? [];
    if (jsBreakpointIds.isNotEmpty) {
      final breakpointIds = jsBreakpointIds
          .map((id) => _breakpoints._dartIdByJsId[id])
          // In case the breakpoint was set in Chrome DevTools outside of
          // package:dwds.
          .where((entry) => entry != null)
          .toSet();
      final pauseBreakpoints = isolate.breakpoints
          ?.where((bp) => breakpointIds.contains(bp.id))
          .toList();
      event = Event(
        kind: EventKind.kPauseBreakpoint,
        timestamp: timestamp,
        isolate: inspector.isolateRef,
      )..pauseBreakpoints = pauseBreakpoints;
    } else if (e.reason == 'exception' || e.reason == 'assert') {
      InstanceRef? exception;

      if (e.data is Map<String, dynamic>) {
        final map = e.data as Map<String, dynamic>;
        if (map['type'] == 'object') {
          final obj = RemoteObject(map);
          exception = await inspector.instanceRefFor(obj);
          if (exception != null && inspector.isNativeJsError(exception)) {
            if (obj.description != null) {
              // Create a string exception object.
              final description =
                  await inspector.mapExceptionStackTrace(obj.description!);
              exception = await inspector.instanceRefFor(description);
            } else {
              exception = null;
            }
          }
        }
      }

      event = Event(
        kind: EventKind.kPauseException,
        timestamp: timestamp,
        isolate: inspector.isolateRef,
        exception: exception,
      );
    } else {
      // Continue stepping until we hit a dart location,
      // avoiding stepping through library loading code.
      if (_isStepping) {
        final scriptId = _frameScriptId(e);
        if (scriptId == null) {
          logger.severe('Stepping failed: '
              'cannot find script id for event $e');
          throw StateError('Stepping failed on event $e');
        }
        final url = urlForScriptId(scriptId);
        if (url == null) {
          logger.severe('Stepping failed: '
              'cannot find url for script $scriptId');
          throw StateError('Stepping failed in script $scriptId');
        }

        if (url.contains(
          globalToolConfiguration.loadStrategy.loadLibrariesModule,
        )) {
          await _remoteDebugger.stepOut();
          return;
        } else if ((await _sourceLocation(e)) == null) {
          // TODO(grouma) - In the future we should send all previously computed
          // skipLists.
          await _remoteDebugger.stepInto(
            params: {
              'skipList': _skipLists.compute(
                scriptId,
                await _locations.locationsForUrl(url),
              ),
            },
          );
          return;
        }
      }
      event = Event(
        kind: EventKind.kPauseInterrupted,
        timestamp: timestamp,
        isolate: inspector.isolateRef,
      );
    }

    // Calculate the frames (and handle any exceptions that may occur).
    stackComputer = FrameComputer(
      this,
      e.getCallFrames().toList(),
      asyncStackTrace: e.asyncStackTrace,
    );

    try {
      final frames = await stackComputer!.calculateFrames(limit: 1);
      event.topFrame = frames.isNotEmpty ? frames.first : null;
    } catch (e, s) {
      // TODO: Return information about the error to the user.
      logger.warning('Error calculating Dart frames', e, s);
    }

    // TODO(elliette): https://github.com/dart-lang/webdev/issues/1501 Re-enable
    // after checking with Chrome team if there is a way to check if the Chrome
    // DevTools is showing an overlay. Both cannot be shown at the same time.
    // _showPausedOverlay();
    isolate.pauseEvent = event;
    _streamNotify('Debug', event);
  }

  /// Handles resume events coming from the Chrome connection.
  void _resumeHandler(DebuggerResumedEvent? _) {
    // We can receive a resume event in the middle of a reload which will result
    // in a null isolate.
    final isolate = inspector.isolate;

    stackComputer = null;
    final event = Event(
      kind: EventKind.kResume,
      timestamp: DateTime.now().millisecondsSinceEpoch,
      isolate: inspector.isolateRef,
    );

    // TODO(elliette): https://github.com/dart-lang/webdev/issues/1501 Re-enable
    // after checking with Chrome team if there is a way to check if the Chrome
    // DevTools is showing an overlay. Both cannot be shown at the same time.
    // _hidePausedOverlay();
    isolate.pauseEvent = event;
    _streamNotify('Debug', event);
  }

  /// Handles targetCrashed events coming from the Chrome connection.
  void _crashHandler(TargetCrashedEvent _) {
    // We can receive a resume event in the middle of a reload which will result
    // in a null isolate.
    final isolate = inspector.isolate;

    stackComputer = null;
    final event = Event(
      kind: EventKind.kIsolateExit,
      timestamp: DateTime.now().millisecondsSinceEpoch,
      isolate: inspector.isolateRef,
    );
    isolate.pauseEvent = event;
    _streamNotify('Isolate', event);
    logger.severe('Target crashed!');
  }

  WipCallFrame? jsFrameForIndex(int frameIndex) {
    final computer = stackComputer;
    if (computer == null) {
      throw RPCError(
        'evaluateInFrame',
        106,
        'Cannot evaluate on a call frame when the program is not paused',
      );
    }
    return computer.jsFrameForIndex(frameIndex);
  }

  /// Evaluate [expression] by calling Chrome's Runtime.evaluateOnCallFrame on
  /// the call frame with index [frameIndex] in the currently saved stack.
  ///
  /// If the program is not paused, so there is no current stack, throws a
  /// [StateError].
  Future<RemoteObject> evaluateJsOnCallFrameIndex(
    int frameIndex,
    String expression,
  ) {
    final index = jsFrameForIndex(frameIndex)?.callFrameId;
    if (index == null) {
      // This might happen on async frames.
      throw StateError('No frame for frame index: $index');
    }
    return evaluateJsOnCallFrame(index, expression);
  }

  /// Evaluate [expression] by calling Chrome's Runtime.evaluateOnCallFrame on
  /// the call frame with id [callFrameId].
  Future<RemoteObject> evaluateJsOnCallFrame(
    String callFrameId,
    String expression,
  ) async {
    // TODO(alanknight): Support a version with arguments if needed.
    try {
      return await _remoteDebugger.evaluateOnCallFrame(callFrameId, expression);
    } on ExceptionDetails catch (e) {
      throw ChromeDebugException(
        e.json,
        evalContents: expression,
      );
    }
  }
}

Future<T> sendCommandAndValidateResult<T>(
  RemoteDebugger remoteDebugger, {
  required String method,
  required String resultField,
  Map<String, dynamic>? params,
}) async {
  final response = await remoteDebugger.sendCommand(method, params: params);
  final result = response.result?[resultField];
  if (result == null) {
    throw RPCError(
      method,
      RPCErrorKind.kInternalError.code,
      '$resultField not found in result from sendCommand',
      params,
    );
  }
  return result;
}

/// Returns the Dart line number for the provided breakpoint.
int _lineNumberFor(Breakpoint breakpoint) =>
    int.parse(breakpoint.id!.split('#').last.split(':').first);

/// Returns the Dart column number for the provided breakpoint.
int _columnNumberFor(Breakpoint breakpoint) =>
    int.parse(breakpoint.id!.split('#').last.split(':').last);

/// Returns the breakpoint ID for the provided Dart script ID and Dart line
/// number.
String breakpointIdFor(String scriptId, int line, int column) =>
    'bp/$scriptId#$line:$column';

/// Keeps track of the Dart and JS breakpoint Ids that correspond.
class _Breakpoints extends Domain {
  final _logger = Logger('Breakpoints');
  final _dartIdByJsId = <String, String>{};
  final _jsIdByDartId = <String, String>{};

  final _bpByDartId = <String, Future<Breakpoint>>{};

  final _queue = AtomicQueue();

  final Locations locations;
  final RemoteDebugger remoteDebugger;

  /// The root URI from which the application is served.
  final String root;

  _Breakpoints({
    required this.locations,
    required this.remoteDebugger,
    required this.root,
  });

  Future<Breakpoint> _createBreakpoint(
    String id,
    String scriptId,
    int line,
    int column,
  ) async {
    final dartScript = inspector.scriptWithId(scriptId);
    final dartScriptUri = dartScript?.uri;
    Location? location;
    if (dartScriptUri != null) {
      final dartUri = DartUri(dartScriptUri, root);
      location = await locations.locationForDart(dartUri, line, column);
    }
    // TODO: Handle cases where a breakpoint can't be set exactly at that line.
    if (location == null) {
      _logger.fine('Failed to set breakpoint $id '
          '($scriptId:$line:$column): '
          'cannot find Dart location.');
      throw RPCError(
          'addBreakpoint',
          102,
          'The VM is unable to add a breakpoint $id '
              'at the specified line or function: ($scriptId:$line:$column): '
              ' cannot find Dart location.');
    }

    try {
      final dartBreakpoint = _dartBreakpoint(dartScript!, location, id);
      final jsBreakpointId = await _setJsBreakpoint(location);
      if (jsBreakpointId == null) {
        _logger.fine('Failed to set breakpoint $id '
            '($scriptId:$line:$column): '
            'cannot set JS breakpoint.');
        throw RPCError(
            'addBreakpoint',
            102,
            'The VM is unable to add a breakpoint $id '
                'at the specified line or function: ($scriptId:$line:$column): '
                'cannot set JS breakpoint at $location');
      }
      _note(jsId: jsBreakpointId, bp: dartBreakpoint);
      return dartBreakpoint;
    } on WipError catch (wipError) {
      throw RPCError('addBreakpoint', 102, '$wipError');
    }
  }

  /// Adds a breakpoint at [scriptId] and [line] or returns an existing one if
  /// present.
  Future<Breakpoint> add(String scriptId, int line, int column) {
    final id = breakpointIdFor(scriptId, line, column);
    return _bpByDartId.putIfAbsent(
      id,
      () => _createBreakpoint(id, scriptId, line, column),
    );
  }

  /// Create a Dart breakpoint at [location] in [dartScript] with [id].
  Breakpoint _dartBreakpoint(
    ScriptRef dartScript,
    Location location,
    String id,
  ) {
    final breakpoint = Breakpoint(
      id: id,
      breakpointNumber: int.parse(createId()),
      resolved: true,
      location: SourceLocation(
        script: dartScript,
        tokenPos: location.tokenPos,
        line: location.dartLocation.line,
        column: location.dartLocation.column,
      ),
      enabled: true,
    )..id = id;
    return breakpoint;
  }

  /// Calls the Chrome protocol setBreakpoint and returns the remote ID.
  Future<String?> _setJsBreakpoint(Location location) {
    // The module can be loaded from a nested path and contain an ETAG suffix.
    final urlRegex = '.*${location.jsLocation.module}.*';
    // Prevent `Aww, snap!` errors when setting multiple breakpoints
    // simultaneously by serializing the requests.
    return _queue.run(() async {
      final breakPointId = await sendCommandAndValidateResult<String>(
        remoteDebugger,
        method: 'Debugger.setBreakpointByUrl',
        resultField: 'breakpointId',
        params: {
          'urlRegex': urlRegex,
          'lineNumber': location.jsLocation.line,
          'columnNumber': location.jsLocation.column,
        },
      );
      return breakPointId;
    });
  }

  /// Records the internal Dart <=> JS breakpoint id mapping and adds the
  /// breakpoint to the current isolates list of breakpoints.
  void _note({required Breakpoint bp, required String jsId}) {
    final bpId = bp.id;
    if (bpId != null) {
      _dartIdByJsId[jsId] = bpId;
      _jsIdByDartId[bpId] = jsId;
      final isolate = inspector.isolate;
      isolate.breakpoints?.add(bp);
    }
  }

  Future<Breakpoint?> remove({
    required String jsId,
    required String dartId,
  }) async {
    final isolate = inspector.isolate;
    _dartIdByJsId.remove(jsId);
    _jsIdByDartId.remove(dartId);
    isolate.breakpoints?.removeWhere((b) => b.id == dartId);
    return await _bpByDartId.remove(dartId);
  }

  Future<Breakpoint>? breakpointFor(String dartId) => _bpByDartId[dartId];
  String? jsIdFor(String dartId) => _jsIdByDartId[dartId];
}

final escapedPipe = '\$124';
final escapedPound = '\$35';

/// Reformats a JS member name to make it look more Dart-like.
///
/// Logic copied from build/build_web_compilers/web/stack_trace_mapper.dart.
/// TODO(https://github.com/dart-lang/sdk/issues/38869): Remove this logic when
/// DDC stack trace deobfuscation is overhauled.
String _prettifyMember(String member) {
  member = member.replaceAll(escapedPipe, '|');
  if (member.contains('|')) {
    return _prettifyExtension(member);
  } else {
    if (member.startsWith('[') && member.endsWith(']')) {
      member = member.substring(1, member.length - 1);
    }
    return member;
  }
}

/// Reformats a JS member name as an extension method invocation.
String _prettifyExtension(String member) {
  var isSetter = false;
  final pipeIndex = member.indexOf('|');
  final spaceIndex = member.indexOf(' ');
  final poundIndex = member.indexOf(escapedPound);
  if (spaceIndex >= 0) {
    // Here member is a static field or static getter/setter.
    isSetter = member.substring(0, spaceIndex) == 'set';
    member = member.substring(spaceIndex + 1, member.length);
  } else if (poundIndex >= 0) {
    // Here member is a tear-off or local property getter/setter.
    isSetter = member.substring(pipeIndex + 1, poundIndex) == 'set';
    member = member.replaceRange(pipeIndex + 1, poundIndex + 3, '');
  } else {
    final body = member.substring(pipeIndex + 1, member.length);
    if (body.startsWith('unary') || body.startsWith('\$')) {
      // Here member's an operator, so it's safe to unescape everything lazily.
      member = _unescape(member);
    }
  }
  member = member.replaceAll('|', '.');
  return isSetter ? '$member=' : member;
}

/// Un-escapes a DDC-escaped JS identifier name.
///
/// Identifier names that contain illegal JS characters are escaped by DDC to a
/// decimal representation of the symbol's UTF-16 value.
/// Warning: this greedily escapes characters, so it can be unsafe in the event
/// that an escaped sequence precedes a number literal in the JS name.
String _unescape(String name) {
  return name.replaceAllMapped(
    RegExp(r'\$[0-9]+'),
    (m) => String.fromCharCode(int.parse(name.substring(m.start + 1, m.end))),
  );
}
