// 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:math' as math;

import 'package:dwds/src/config/tool_configuration.dart';
import 'package:dwds/src/connections/app_connection.dart';
import 'package:dwds/src/debugging/classes.dart';
import 'package:dwds/src/debugging/debugger.dart';
import 'package:dwds/src/debugging/execution_context.dart';
import 'package:dwds/src/debugging/inspector.dart';
import 'package:dwds/src/debugging/instance.dart';
import 'package:dwds/src/debugging/libraries.dart';
import 'package:dwds/src/debugging/location.dart';
import 'package:dwds/src/debugging/metadata/provider.dart';
import 'package:dwds/src/debugging/remote_debugger.dart';
import 'package:dwds/src/loaders/ddc_library_bundle.dart';
import 'package:dwds/src/readers/asset_reader.dart';
import 'package:dwds/src/utilities/conversions.dart';
import 'package:dwds/src/utilities/dart_uri.dart';
import 'package:dwds/src/utilities/domain.dart';
import 'package:dwds/src/utilities/objects.dart';
import 'package:dwds/src/utilities/server.dart';
import 'package:dwds/src/utilities/shared.dart';
import 'package:logging/logging.dart';
import 'package:vm_service/vm_service.dart';
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';

/// An inspector for a running Dart application contained in the
/// [WipConnection].
///
/// Provides information about currently loaded scripts and objects and support
/// for eval.
class ChromeAppInspector extends AppInspector {
  final _logger = Logger('AppInspector');

  final RemoteDebugger remoteDebugger;
  final ExecutionContext _executionContext;

  @override
  late final ChromeLibraryHelper libraryHelper = ChromeLibraryHelper(this);

  late ChromeAppClassHelper _classHelper;
  late ChromeAppInstanceHelper _instanceHelper;

  final AssetReader _assetReader;
  final Locations _locations;

  /// JavaScript expression that evaluates to the Dart stack trace mapper.
  static const stackTraceMapperExpression = '\$dartStackTraceUtility.mapper';

  /// Regex used to extract the message from an exception description.
  static final exceptionMessageRegex = RegExp(r'^.*$', multiLine: true);

  /// Regex used to extract a stack trace line from the exception description.
  static final stackTraceLineRegex = RegExp(r'^\s*at\s.*$', multiLine: true);

  ChromeAppInspector._(
    super.appConnection,
    super.isolate,
    this.remoteDebugger,
    this._assetReader,
    this._locations,
    super.root,
    this._executionContext,
  );

  /// Reset all caches and recompute any mappings.
  ///
  /// Should be called across hot reloads with a valid [ModifiedModuleReport].
  @override
  Future<void> initialize({ModifiedModuleReport? modifiedModuleReport}) async {
    await super.initialize(modifiedModuleReport: modifiedModuleReport);

    // TODO(srujzs): We can invalidate these in a smarter way instead of
    // reinitializing when doing a hot reload, but these helpers recompute info
    // on demand later and therefore are not in the critical path.
    _classHelper = ChromeAppClassHelper(this);
    _instanceHelper = ChromeAppInstanceHelper(this);

    // Populate the extension RPCs in the isolate.
    await getExtensionRpcs();
  }

  static Future<ChromeAppInspector> create(
    AppConnection appConnection,
    RemoteDebugger remoteDebugger,
    AssetReader assetReader,
    Locations locations,
    String root,
    Debugger debugger,
    ExecutionContext executionContext,
  ) async {
    final id = createId();
    final time = DateTime.now().millisecondsSinceEpoch;
    final name = 'main()';
    final isolate = Isolate(
      id: id,
      number: id,
      name: name,
      startTime: time,
      runnable: true,
      pauseOnExit: false,
      pauseEvent: Event(
        kind: EventKind.kPauseStart,
        timestamp: time,
        isolate: IsolateRef(
          id: id,
          name: name,
          number: id,
          isSystemIsolate: false,
        ),
      ),
      livePorts: 0,
      libraries: [],
      breakpoints: [],
      exceptionPauseMode: debugger.pauseState,
      isSystemIsolate: false,
      isolateFlags: [],
      extensionRPCs: [],
    );
    final inspector = ChromeAppInspector._(
      appConnection,
      isolate,
      remoteDebugger,
      assetReader,
      locations,
      root,
      executionContext,
    );

    debugger.updateInspector(inspector);
    await inspector.initialize();
    return inspector;
  }

  /// Returns the ID for the execution context or null if not found.
  Future<int?> get contextId async {
    try {
      return await _executionContext.id;
    } catch (e, s) {
      _logger.severe('Missing execution context ID: ', e, s);
      return null;
    }
  }

  /// Get the value of the field named [fieldName] from [receiver].
  Future<RemoteObject> loadField(RemoteObject receiver, String fieldName) {
    final load = globalToolConfiguration.loadStrategy.dartRuntimeDebugger
        .getPropertyJsExpression(fieldName);
    return jsCallFunctionOn(receiver, load, []);
  }

  /// Call a method by name on [receiver], with arguments [positionalArgs] and
  /// [namedArgs].
  Future<RemoteObject> _invokeMethod(
    RemoteObject receiver,
    String methodName, [
    List<RemoteObject> positionalArgs = const [],
    Map namedArgs = const {},
  ]) async {
    // TODO(alanknight): Support named arguments.
    if (namedArgs.isNotEmpty) {
      throw UnsupportedError('Named arguments are not yet supported');
    }
    // We use the JS pseudo-variable 'arguments' to get the list of all arguments.
    final send = globalToolConfiguration.loadStrategy.dartRuntimeDebugger
        .callInstanceMethodJsExpression(methodName);
    final remote = await jsCallFunctionOn(receiver, send, positionalArgs);
    return remote;
  }

  /// Calls Chrome's Runtime.callFunctionOn method.
  ///
  /// [evalExpression] should be a JS function definition that can accept
  /// [arguments].
  Future<RemoteObject> jsCallFunctionOn(
    RemoteObject receiver,
    String evalExpression,
    List<RemoteObject> arguments, {
    bool returnByValue = false,
  }) async {
    final jsArguments = arguments.map(callArgumentFor).toList();
    final response = await remoteDebugger.sendCommand(
      'Runtime.callFunctionOn',
      params: {
        'functionDeclaration': evalExpression,
        'arguments': jsArguments,
        'objectId': receiver.objectId,
        'returnByValue': returnByValue,
      },
    );
    final result = getResultOrHandleError(
      response,
      evalContents: evalExpression,
    );
    return RemoteObject(result);
  }

  /// Calls Chrome's Runtime.callFunctionOn method with a global function.
  ///
  /// [evalExpression] should be a JS function definition that can accept
  /// [arguments].
  Future<RemoteObject> _jsCallFunction(
    String evalExpression,
    List<Object> arguments, {
    bool returnByValue = false,
  }) async {
    final jsArguments = arguments.map(callArgumentFor).toList();
    final response = await remoteDebugger.sendCommand(
      'Runtime.callFunctionOn',
      params: {
        'functionDeclaration': evalExpression,
        'arguments': jsArguments,
        'executionContextId': await contextId,
        'returnByValue': returnByValue,
      },
    );
    final result = getResultOrHandleError(
      response,
      evalContents: evalExpression,
    );
    return RemoteObject(result);
  }

  /// Invoke the function named [selector] on the object identified by
  /// [targetId].
  ///
  /// The [targetId] can be the URL of a Dart library, in which case this means
  /// invoking a top-level function. The [arguments] are always strings that are
  /// Dart object Ids (which can also be Chrome RemoteObject objectIds that are
  /// for non-Dart JS objects.)
  Future<RemoteObject> invoke(
    String targetId,
    String selector, [
    List<dynamic> arguments = const [],
  ]) async {
    final remoteArguments = arguments
        .cast<String>()
        .map(remoteObjectFor)
        .toList();
    // We special case the Dart library, where invokeMethod won't work because
    // it's not really a Dart object.
    if (isLibraryId(targetId)) {
      final library = await getObject(targetId) as Library;
      return await _invokeLibraryFunction(library, selector, remoteArguments);
    } else {
      return _invokeMethod(
        remoteObjectFor(targetId),
        selector,
        remoteArguments,
      );
    }
  }

  /// Invoke the function named [selector] from [library] with [arguments].
  Future<RemoteObject> _invokeLibraryFunction(
    Library library,
    String selector,
    List<RemoteObject> arguments,
  ) {
    final libraryUri = library.uri;
    if (libraryUri == null) {
      throwInvalidParam('invoke', 'library uri is null');
    }
    return globalToolConfiguration.loadStrategy is DdcLibraryBundleStrategy
        ? _evaluateLibraryMethodWithDdcLibraryBundle(
            libraryUri,
            selector,
            arguments,
          )
        : _evaluateInLibrary(
            libraryUri,
            'function () { return this.$selector.apply(this, arguments); }',
            arguments,
          );
  }

  /// Evaluate [expression] by calling Chrome's Runtime.evaluate.
  Future<RemoteObject> jsEvaluate(
    String expression, {
    bool returnByValue = false,
    bool awaitPromise = false,
  }) async {
    // TODO(alanknight): Support a version with arguments if needed.
    final response = await remoteDebugger.sendCommand(
      'Runtime.evaluate',
      params: {
        'expression': expression,
        'returnByValue': returnByValue,
        'awaitPromise': awaitPromise,
        'contextId': await contextId,
      },
    );
    final result = getResultOrHandleError(response, evalContents: expression);
    return RemoteObject(result);
  }

  /// Evaluate the JS function with source [jsFunction] in the context of
  /// the library identified by [libraryUri] with [arguments].
  Future<RemoteObject> _evaluateInLibrary(
    String libraryUri,
    String jsFunction,
    List<RemoteObject> arguments,
  ) async {
    final findLibraryJsExpression = globalToolConfiguration
        .loadStrategy
        .dartRuntimeDebugger
        .callLibraryMethodJsExpression(libraryUri, jsFunction);

    final remoteLibrary = await jsEvaluate(findLibraryJsExpression);
    return jsCallFunctionOn(remoteLibrary, jsFunction, arguments);
  }

  /// Evaluates the specified top-level method [methodName] within the library
  /// identified by [libraryUri] using the Dart Development Compiler (DDC)
  /// library bundle strategy with the given optional [arguments].
  Future<RemoteObject> _evaluateLibraryMethodWithDdcLibraryBundle(
    String libraryUri,
    String methodName, [
    List<RemoteObject> arguments = const [],
  ]) {
    final expression = globalToolConfiguration.loadStrategy.dartRuntimeDebugger
        .callLibraryMethodJsExpression(libraryUri, methodName);
    return _jsCallFunction(expression, arguments);
  }

  /// Call [function] with objects referred by [argumentIds] as arguments.
  Future<RemoteObject> callFunction(
    String function,
    Iterable<String> argumentIds,
  ) {
    final arguments = argumentIds.map(remoteObjectFor).toList();
    return _jsCallFunction(function, arguments);
  }

  Future<InstanceRef?> instanceRefFor(Object value) =>
      _instanceHelper.instanceRefFor(value);

  Future<Instance?> instanceFor(RemoteObject value) =>
      _instanceHelper.instanceFor(value);

  Future<Library?> getLibrary(String objectId) async {
    final libraryRef = await libraryRefFor(objectId);
    if (libraryRef == null) return null;
    return libraryHelper.libraryFor(libraryRef);
  }

  Future<Obj> getObject(String objectId, {int? offset, int? count}) async {
    try {
      final library = await getLibrary(objectId);
      if (library != null) {
        return library;
      }
      final clazz = await _classHelper.forObjectId(objectId);
      if (clazz != null) {
        return clazz;
      }
      final scriptRef = scriptRefsById[objectId];
      if (scriptRef != null) {
        return _getScript(scriptRef);
      }
      final instance = await _instanceHelper.instanceFor(
        remoteObjectFor(objectId),
        offset: offset,
        count: count,
      );
      if (instance != null) {
        return instance;
      }
    } catch (e, s) {
      _logger.fine('getObject $objectId failed', e, s);
      rethrow;
    }
    throw UnsupportedError(
      'Only libraries, instances, classes, and scripts '
      'are supported for getObject',
    );
  }

  Future<Script> _getScript(ScriptRef scriptRef) async {
    final scriptId = scriptRef.id;
    final scriptUri = scriptRef.uri;
    if (scriptId == null || scriptUri == null) {
      throwInvalidParam('getObject', 'No script info for script $scriptRef');
    }
    final serverPath = DartUri(scriptUri, root).serverPath;
    final source = await _assetReader.dartSourceContents(serverPath);
    if (source == null) {
      throwInvalidParam(
        'getObject',
        'No source for $scriptRef  with serverPath: $serverPath',
      );
    }
    final libraryId = scriptIdToLibraryId[scriptId];
    if (libraryId == null) {
      throwInvalidParam('getObject', 'No library for script $scriptRef');
    }
    return Script(
        uri: scriptRef.uri,
        library: await libraryRefFor(libraryId),
        id: scriptId,
      )
      ..tokenPosTable = await _locations.tokenPosTableFor(serverPath)
      ..source = source;
  }

  Future<MemoryUsage> getMemoryUsage() async {
    final response = await remoteDebugger.sendCommand('Runtime.getHeapUsage');
    final result = response.result;
    if (result == null) {
      throw RPCError(
        'getMemoryUsage',
        RPCErrorKind.kInternalError.code,
        'Null result from chrome Devtools.',
      );
    }
    final jsUsage = HeapUsage(result);
    final usage = MemoryUsage.parse({
      'heapUsage': jsUsage.usedSize,
      'heapCapacity': jsUsage.totalSize,
      'externalUsage': 0,
    });
    if (usage == null) {
      throw RPCError(
        'getMemoryUsage',
        RPCErrorKind.kInternalError.code,
        'Failed to parse memory usage result.',
      );
    }
    return usage;
  }

  /// Return the VM SourceReport for the given parameters.
  ///
  /// Currently this implements the 'PossibleBreakpoints' report kind.
  Future<SourceReport> getSourceReport(
    List<String> reports, {
    String? scriptId,
  }) {
    if (reports.contains(SourceReportKind.kCoverage)) {
      throwInvalidParam(
        'getSourceReport',
        'Source report kind ${SourceReportKind.kCoverage} not supported',
      );
    }

    if (reports.isEmpty) {
      throwInvalidParam(
        'getSourceReport',
        'Invalid parameter: no value for source report kind provided.',
      );
    }

    if (reports.length > 1 ||
        reports.first != SourceReportKind.kPossibleBreakpoints) {
      throwInvalidParam('getSourceReport', 'Unsupported source report kind.');
    }

    return _getPossibleBreakpoints(scriptId);
  }

  Future<SourceReport> _getPossibleBreakpoints(String? scriptId) async {
    // TODO(devoncarew): Consider adding some caching for this method.

    final scriptRef = scriptWithId(scriptId);
    if (scriptRef == null) {
      throwInvalidParam('getSourceReport', 'scriptRef not found for $scriptId');
    }
    final scriptUri = scriptRef.uri;
    if (scriptUri == null) {
      throwInvalidParam('getSourceReport', 'scriptUri not found for $scriptId');
    }

    final dartUri = DartUri(scriptUri, root);
    final mappedLocations = await _locations.locationsForDart(
      dartUri.serverPath,
    );
    // Unlike the Dart VM, the token positions match exactly to the possible
    // breakpoints. This is because the token positions are derived from the
    // DDC source maps which Chrome also uses.
    final tokenPositions = <int>[
      for (final location in mappedLocations) location.tokenPos,
    ];
    tokenPositions.sort();

    final range = SourceReportRange(
      scriptIndex: 0,
      startPos: tokenPositions.isEmpty ? -1 : tokenPositions.first,
      endPos: tokenPositions.isEmpty ? -1 : tokenPositions.last,
      compiled: true,
      possibleBreakpoints: tokenPositions,
    );

    final ranges = [range];
    return SourceReport(scripts: [scriptRef], ranges: ranges);
  }

  /// Calls the Chrome Runtime.getProperties API for the object with [objectId].
  ///
  /// Note that the property names are JS names, e.g.
  /// Symbol(DartClass.actualName) and will need to be converted. For a system
  /// List or Map, [offset] and/or [count] can be provided to indicate a desired
  /// range of entries. They will be ignored if there is no [length].
  Future<List<Property>> getProperties(
    String objectId, {
    int? offset,
    int? count,
    int? length,
  }) async {
    var rangeId = objectId;
    // Ignore offset/count if there is no length:
    if (length != null) {
      if (_isEmptyRange(offset: offset, count: count, length: length)) {
        return [];
      }
      if (_isSubRange(offset: offset, count: count)) {
        final range = await _subRange(
          objectId,
          offset: offset ?? 0,
          count: count,
          length: length,
        );
        rangeId = range.objectId ?? rangeId;
      }
    }
    final jsProperties = await sendCommandAndValidateResult<List>(
      remoteDebugger,
      method: 'Runtime.getProperties',
      resultField: 'result',
      params: {'objectId': rangeId, 'ownProperties': true},
    );
    return jsProperties
        .map<Property>((each) => Property(each as Map<String, dynamic>))
        .where(_isVisibleProperty)
        .toList();
  }

  bool _isVisibleProperty(Property property) {
    // Filter out any RTI objects from the new DDC type system. See:
    // https://github.com/dart-lang/webdev/issues/2316
    final isRtiObject =
        property.value?.className?.startsWith('dart_rti.Rti') ?? false;
    return !isRtiObject;
  }

  /// Calculate the number of available elements in the range.
  static int _calculateRangeCount({
    int? count,
    required int offset,
    required int length,
  }) => count == null ? length - offset : math.min(count, length - offset);

  /// Find a sub-range of the entries for a Map/List when offset and/or count
  /// have been specified on a getObject request.
  ///
  /// If the object referenced by [id] is not a system List or Map then this
  /// will just return a RemoteObject for it and ignore [offset], [count] and
  /// [length]. If it is, then [length] should be the number of entries in the
  /// List/Map and [offset] and [count] should indicate the desired range.
  Future<RemoteObject> _subRange(
    String id, {
    required int offset,
    required int length,
    int? count,
  }) async {
    // TODO(#809): Sometimes we already know the type of the object, and
    // we could take advantage of that to short-circuit.
    final receiver = remoteObjectFor(id);
    final rangeCount = _calculateRangeCount(
      count: count,
      offset: offset,
      length: length,
    );
    final args = [
      offset,
      rangeCount,
    ].map(dartIdFor).map(remoteObjectFor).toList();
    // If this is a List, just call sublist. If it's a Map, get the entries, but
    // avoid doing a toList on a large map using skip/take to get the section we
    // want. To make those alternatives easier in JS, pass both count and end.
    final expression = globalToolConfiguration.loadStrategy.dartRuntimeDebugger
        .getSubRangeJsExpression();

    return await jsCallFunctionOn(receiver, expression, args);
  }

  static bool _isEmptyRange({required int length, int? offset, int? count}) {
    if (count == 0) return true;
    if (offset == null) return false;
    return offset >= length;
  }

  static bool _isSubRange({int? offset, int? count}) {
    if (offset == 0 && count == null) return false;
    return offset != null || count != null;
  }

  /// Returns true for objects we display for the user.
  bool isDisplayableObject(Object? object) =>
      object is Sentinel ||
      object is InstanceRef &&
          !isNativeJsObject(object) &&
          !isNativeJsError(object);

  /// Returns true for non-dart JavaScript objects.
  bool isNativeJsObject(InstanceRef instanceRef) {
    return _instanceHelper.metadataHelper.isNativeJsObject(
      instanceRef.classRef,
    );
  }

  /// Returns true for JavaScript exceptions.
  bool isNativeJsError(InstanceRef instanceRef) {
    return _instanceHelper.metadataHelper.isNativeJsError(instanceRef.classRef);
  }

  /// Runs an eval on the page to compute all existing registered extensions.
  ///
  /// Combines this with the RPCs registered in the [isolate]. Use this over
  /// [Isolate.extensionRPCs] as this computes a live set.
  ///
  /// Updates [Isolate.extensionRPCs] to this set.
  @override
  Future<Set<String>> getExtensionRpcs() async {
    final expression = globalToolConfiguration.loadStrategy.dartRuntimeDebugger
        .getDartDeveloperExtensionNamesJsExpression();
    final extensionRpcs = <String>{};
    final params = {
      'expression': expression,
      'returnByValue': true,
      'contextId': await contextId,
    };
    try {
      final response = await remoteDebugger.sendCommand(
        'Runtime.evaluate',
        params: params,
      );
      final result = getResultOrHandleError(response, evalContents: expression);
      extensionRpcs.addAll(List.from(result['value'] as List? ?? []));
    } catch (e, s) {
      _logger.severe(
        'Error calling Runtime.evaluate with params $params',
        e,
        s,
      );
    }
    isolate.extensionRPCs = List<String>.of(extensionRpcs);
    return extensionRpcs;
  }

  /// Convert a JS exception description into a description containing
  /// a Dart stack trace.
  Future<String> mapExceptionStackTrace(String description) async {
    RemoteObject mapperResult;
    try {
      mapperResult = await _jsCallFunction(stackTraceMapperExpression, <Object>[
        description,
      ]);
    } catch (_) {
      return description;
    }
    final mappedStack = mapperResult.value?.toString();
    if (mappedStack == null || mappedStack.isEmpty) {
      return description;
    }
    final message = _allLinesBeforeStackTrace(description);
    return '$message$mappedStack';
  }

  String _allLinesBeforeStackTrace(String description) {
    var message = '';
    for (final match in exceptionMessageRegex.allMatches(description)) {
      final isStackTraceLine = stackTraceLineRegex.hasMatch(match[0] ?? '');
      if (isStackTraceLine) break;
      message += '${match[0]}\n';
    }
    return message;
  }
}
