// 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';

import 'package:dwds/src/config/tool_configuration.dart';
import 'package:dwds/src/debugging/inspector.dart';
import 'package:dwds/src/debugging/metadata/class.dart';
import 'package:dwds/src/debugging/metadata/function.dart';
import 'package:dwds/src/utilities/conversions.dart';
import 'package:dwds/src/utilities/domain.dart';
import 'package:dwds/src/utilities/objects.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';

/// Contains a set of methods for getting [Instance]s and [InstanceRef]s.
class InstanceHelper extends Domain {
  final _logger = Logger('InstanceHelper');
  final ClassMetaDataHelper metadataHelper;

  InstanceHelper(AppInspector appInspector)
      : metadataHelper = ClassMetaDataHelper(appInspector) {
    inspector = appInspector;
  }

  static final InstanceRef kNullInstanceRef =
      _primitiveInstanceRef(InstanceKind.kNull, null);

  /// Creates an [InstanceRef] for a primitive [RemoteObject].
  static InstanceRef _primitiveInstanceRef(
    String kind,
    RemoteObject? remoteObject,
  ) {
    final classRef = classRefFor('dart:core', kind);
    return InstanceRef(
      identityHashCode: dartIdFor(remoteObject?.value).hashCode,
      kind: kind,
      classRef: classRef,
      id: dartIdFor(remoteObject?.value),
      valueAsString: '${remoteObject?.value}',
    );
  }

  /// Creates an [Instance] for a primitive [RemoteObject].
  Instance? _primitiveInstance(String kind, RemoteObject? remoteObject) {
    final objectId = remoteObject?.objectId;
    if (objectId == null) return null;
    return Instance(
      identityHashCode: objectId.hashCode,
      id: objectId,
      kind: kind,
      classRef: classRefFor('dart:core', kind),
      valueAsString: '${remoteObject?.value}',
    );
  }

  Instance? _stringInstanceFor(
    RemoteObject? remoteObject,
    int? offset,
    int? count,
  ) {
    // TODO(#777) Consider a way of not passing the whole string around (in the
    // ID) in order to find a substring.
    final objectId = remoteObject?.objectId;
    if (objectId == null) return null;
    final fullString = stringFromDartId(objectId);
    var preview = fullString;
    var truncated = false;
    if (offset != null || count != null) {
      truncated = true;
      final start = offset ?? 0;
      final end = count == null ? null : min(start + count, fullString.length);
      preview = fullString.substring(start, end);
    }
    return Instance(
      identityHashCode: createId().hashCode,
      kind: InstanceKind.kString,
      classRef: classRefForString,
      id: createId(),
      valueAsString: preview,
      valueAsStringIsTruncated: truncated,
      length: fullString.length,
      count: (truncated ? preview.length : null),
      offset: (truncated ? offset : null),
    );
  }

  Instance? _closureInstanceFor(RemoteObject remoteObject) {
    final objectId = remoteObject.objectId;
    if (objectId == null) return null;
    final result = Instance(
      kind: InstanceKind.kClosure,
      id: objectId,
      identityHashCode: remoteObject.objectId.hashCode,
      classRef: classRefForClosure,
    );
    return result;
  }

  /// Create an [Instance] for the given [remoteObject].
  ///
  /// Does a remote eval to get instance information. Returns null if there
  /// isn't a corresponding instance. For enumerable objects, [offset] and
  /// [count] allow retrieving a sub-range of properties.
  Future<Instance?> instanceFor(
    RemoteObject? remoteObject, {
    int? offset,
    int? count,
  }) async {
    final primitive = _primitiveInstanceOrNull(remoteObject, offset, count);
    if (primitive != null) {
      return primitive;
    }
    final objectId = remoteObject?.objectId;
    if (remoteObject == null || objectId == null) return null;

    final metaData = await metadataHelper.metaDataFor(remoteObject);

    final classRef = metaData?.classRef;
    if (metaData == null || classRef == null) return null;

    switch (metaData.runtimeKind) {
      case RuntimeObjectKind.function:
        return _closureInstanceFor(remoteObject);
      case RuntimeObjectKind.recordType:
        return await _recordTypeInstanceFor(
          metaData,
          remoteObject,
          offset: offset,
          count: count,
        );
      case RuntimeObjectKind.type:
        return await _plainTypeInstanceFor(
          metaData,
          remoteObject,
          offset: offset,
          count: count,
        );
      case RuntimeObjectKind.list:
        return await _listInstanceFor(
          metaData,
          remoteObject,
          offset: offset,
          count: count,
        );
      case RuntimeObjectKind.set:
        return await _setInstanceFor(
          metaData,
          remoteObject,
          offset: offset,
          count: count,
        );
      case RuntimeObjectKind.map:
        return await _mapInstanceFor(
          metaData,
          remoteObject,
          offset: offset,
          count: count,
        );
      case RuntimeObjectKind.record:
        return await _recordInstanceFor(
          metaData,
          remoteObject,
          offset: offset,
          count: count,
        );
      case RuntimeObjectKind.object:
      case RuntimeObjectKind.nativeError:
      case RuntimeObjectKind.nativeObject:
      default:
        return await _plainInstanceFor(
          metaData,
          remoteObject,
          offset: offset,
          count: count,
        );
    }
  }

  /// If [remoteObject] represents a primitive, return an [Instance] for it,
  /// otherwise return null.
  Instance? _primitiveInstanceOrNull(
    RemoteObject? remoteObject,
    int? offset,
    int? count,
  ) {
    switch (remoteObject?.type ?? 'undefined') {
      case 'string':
        return _stringInstanceFor(remoteObject, offset, count);
      case 'number':
        return _primitiveInstance(InstanceKind.kDouble, remoteObject);
      case 'boolean':
        return _primitiveInstance(InstanceKind.kBool, remoteObject);
      case 'undefined':
        return _primitiveInstance(InstanceKind.kNull, remoteObject);
      default:
        return null;
    }
  }

  /// Create a bound field for [property] in an instance of [classRef].
  Future<BoundField> _fieldFor(Property property, ClassRef classRef) async {
    final instance = await _instanceRefForRemote(property.value);
    // TODO(annagrin): convert JS name to dart and fill missing information.
    //https://github.com/dart-lang/sdk/issues/46723
    return BoundField(
      name: property.name,
      decl: FieldRef(
        // TODO(grouma) - Convert JS name to Dart.
        name: property.name,
        declaredType: InstanceRef(
          kind: InstanceKind.kType,
          classRef: instance?.classRef,
          identityHashCode: createId().hashCode,
          id: createId(),
        ),
        owner: classRef,
        isConst: false,
        isFinal: false,
        isStatic: false,
        id: createId(),
      ),
      value: instance,
    );
  }

  /// Create a plain instance of [classRef] from [remoteObject] and the JS
  /// properties [properties].
  Future<Instance?> _plainInstanceFor(
    ClassMetaData metaData,
    RemoteObject remoteObject, {
    int? offset,
    int? count,
  }) async {
    final objectId = remoteObject.objectId;
    if (objectId == null) return null;

    final properties = await inspector.getProperties(
      objectId,
      offset: offset,
      count: count,
      length: metaData.length,
    );
    final dartProperties = await _dartFieldsFor(properties, remoteObject);
    var boundFields = await Future.wait(
      dartProperties
          .map<Future<BoundField>>((p) => _fieldFor(p, metaData.classRef)),
    );
    boundFields = boundFields
        .where((bv) => inspector.isDisplayableObject(bv.value))
        .toList()
      ..sort(_compareBoundFields);
    final result = Instance(
      kind: InstanceKind.kPlainInstance,
      id: objectId,
      identityHashCode: remoteObject.objectId.hashCode,
      classRef: metaData.classRef,
      fields: boundFields,
    );
    return result;
  }

  int _compareBoundFields(BoundField a, BoundField b) {
    final aName = a.decl?.name;
    final bName = b.decl?.name;
    if (aName == null) return bName == null ? 0 : -1;
    if (bName == null) return 1;
    return aName.compareTo(bName);
  }

  /// The associations for a Dart Map or IdentityMap.
  ///
  /// Returns a range of [count] associations, if available, starting from
  /// the [offset].
  ///
  /// If [offset] is `null`, assumes 0 offset.
  /// If [count] is `null`, return all fields starting from the offset.
  Future<List<MapAssociation>> _mapAssociations(
    RemoteObject map, {
    int? offset,
    int? count,
  }) async {
    // We do this in in awkward way because we want the keys and values, but we
    // can't return things by value or some Dart objects will come back as
    // values that we need to be RemoteObject, e.g. a List of int.
    final expression = _jsRuntimeFunctionCall('getMapElements(this)');

    final keysAndValues = await inspector.jsCallFunctionOn(map, expression, []);
    final keys = await inspector.loadField(keysAndValues, 'keys');
    final values = await inspector.loadField(keysAndValues, 'values');
    final keysInstance = await instanceFor(keys, offset: offset, count: count);
    final valuesInstance =
        await instanceFor(values, offset: offset, count: count);
    final associations = <MapAssociation>[];
    final keyElements = keysInstance?.elements;
    final valueElements = valuesInstance?.elements;
    if (keyElements != null && valueElements != null) {
      Map.fromIterables(keyElements, valueElements).forEach((key, value) {
        associations.add(MapAssociation(key: key, value: value));
      });
    }
    return associations;
  }

  /// Create a Map instance with class [classRef] from [remoteObject].
  ///
  /// Returns an instance containing [count] associations, if available,
  /// starting from the [offset].
  ///
  /// If [offset] is `null`, assumes 0 offset.
  /// If [count] is `null`, return all fields starting from the offset.
  /// [length] is the expected length of the whole object, read from
  /// the [ClassMetaData].
  Future<Instance?> _mapInstanceFor(
    ClassMetaData metaData,
    RemoteObject remoteObject, {
    int? offset,
    int? count,
  }) async {
    final objectId = remoteObject.objectId;
    if (objectId == null) return null;

    // Maps are complicated, do an eval to get keys and values.
    final associations =
        await _mapAssociations(remoteObject, offset: offset, count: count);
    final rangeCount = _calculateRangeCount(
      count: count,
      elementCount: associations.length,
      length: metaData.length,
    );
    return Instance(
      identityHashCode: remoteObject.objectId.hashCode,
      kind: InstanceKind.kMap,
      id: objectId,
      classRef: metaData.classRef,
      length: metaData.length,
      offset: offset,
      count: rangeCount,
      associations: associations,
    );
  }

  /// Create a List instance of [classRef] from [remoteObject].
  ///
  /// Returns an instance containing [count] elements, if available,
  /// starting from the [offset].
  ///
  /// If [offset] is `null`, assumes 0 offset.
  /// If [count] is `null`, return all fields starting from the offset.
  /// [length] is the expected length of the whole object, read from
  /// the [ClassMetaData].
  Future<Instance?> _listInstanceFor(
    ClassMetaData metaData,
    RemoteObject remoteObject, {
    int? offset,
    int? count,
  }) async {
    final objectId = remoteObject.objectId;
    if (objectId == null) return null;

    final elements = await _listElements(
      remoteObject,
      offset: offset,
      count: count,
      length: metaData.length,
    );
    final rangeCount = _calculateRangeCount(
      count: count,
      elementCount: elements.length,
      length: metaData.length,
    );
    return Instance(
      identityHashCode: remoteObject.objectId.hashCode,
      kind: InstanceKind.kList,
      id: objectId,
      classRef: metaData.classRef,
      length: metaData.length,
      elements: elements,
      offset: offset,
      count: rangeCount,
    );
  }

  /// The elements for a Dart List.
  ///
  /// Returns a range of [count] elements, if available, starting from
  /// the [offset].
  ///
  /// If [offset] is `null`, assumes 0 offset.
  /// If [count] is `null`, return all fields starting from the offset.
  /// [length] is the expected length of the whole object, read from
  /// the [ClassMetaData].
  Future<List<InstanceRef?>> _listElements(
    RemoteObject list, {
    int? offset,
    int? count,
    int? length,
  }) async {
    final properties = await inspector.getProperties(
      list.objectId!,
      offset: offset,
      count: count,
      length: length,
    );

    // Filter out all non-indexed properties
    final elements = _indexedListProperties(properties);

    final rangeCount = _calculateRangeCount(
      count: count,
      elementCount: elements.length,
      length: length,
    );
    final range = elements.sublist(0, rangeCount);

    return Future.wait(
      range.map((element) => _instanceRefForRemote(element.value)),
    );
  }

  /// Return elements of the list from [properties].
  ///
  /// Ignore any non-elements like 'length', 'fixed$length', etc.
  static List<Property> _indexedListProperties(List<Property> properties) =>
      properties
          .where((p) => p.name != null && int.tryParse(p.name!) != null)
          .toList();

  /// The field names for a Dart record shape.
  ///
  /// Returns a range of [count] fields, if available, starting from
  /// the [offset].
  ///
  /// If [offset] is `null`, assumes 0 offset.
  /// If [count] is `null`, return all fields starting from the offset.
  /// The [shape] object describes the shape using `positionalCount`
  /// and `named` fields.
  ///
  /// Returns list of field names for the record shape.
  Future<List<dynamic>> _recordShapeFields(
    RemoteObject shape, {
    int? offset,
    int? count,
  }) async {
    final positionalCountObject =
        await inspector.loadField(shape, 'positionalCount');
    if (positionalCountObject == null || positionalCountObject.value is! int) {
      _logger.warning(
        'Unexpected positional count from record: $positionalCountObject',
      );
      return [];
    }

    final namedObject = await inspector.loadField(shape, 'named');
    final positionalCount = positionalCountObject.value as int;
    final positionalOffset = offset ?? 0;
    final positionalAvailable =
        _remainingCount(positionalOffset, positionalCount);
    final positionalRangeCount =
        min(positionalAvailable, count ?? positionalAvailable);
    final positionalElements = [
      for (var i = positionalOffset + 1;
          i <= positionalOffset + positionalRangeCount;
          i++)
        i,
    ];

    // Collect named fields in the requested range.
    // Account for already collected positional fields.
    final namedRangeOffset =
        offset == null ? null : _remainingCount(positionalCount, offset);
    final namedRangeCount =
        count == null ? null : _remainingCount(positionalRangeCount, count);
    final namedInstance = await instanceFor(
      namedObject,
      offset: namedRangeOffset,
      count: namedRangeCount,
    );
    final namedElements =
        namedInstance?.elements?.map((e) => e.valueAsString) ?? [];

    return [
      ...positionalElements,
      ...namedElements,
    ];
  }

  /// The fields for a Dart Record.
  ///
  /// Returns a range of [count] fields, if available, starting from
  /// the [offset].
  ///
  /// If [offset] is `null`, assumes 0 offset.
  /// If [count] is `null`, return all fields starting from the offset.
  Future<List<BoundField>> _recordFields(
    RemoteObject record, {
    int? offset,
    int? count,
  }) async {
    // We do this in in awkward way because we want the keys and values, but we
    // can't return things by value or some Dart objects will come back as
    // values that we need to be RemoteObject, e.g. a List of int.
    final expression = _jsRuntimeFunctionCall('getRecordFields(this)');

    final result = await inspector.jsCallFunctionOn(record, expression, []);
    final fieldNameElements =
        await _recordShapeFields(result, offset: offset, count: count);

    final valuesObject = await inspector.loadField(result, 'values');
    final valuesInstance =
        await instanceFor(valuesObject, offset: offset, count: count);
    final valueElements = valuesInstance?.elements ?? [];

    return _elementsToBoundFields(fieldNameElements, valueElements);
  }

  /// Create a list of `BoundField`s from field [names] and [values].
  List<BoundField> _elementsToBoundFields(
    List<dynamic> names,
    List<dynamic> values,
  ) {
    if (names.length != values.length) {
      _logger.warning('Bound field names and values are not the same length.');
      return [];
    }

    final boundFields = <BoundField>[];
    Map.fromIterables(names, values).forEach((name, value) {
      boundFields.add(BoundField(name: name, value: value));
    });
    return boundFields;
  }

  static int _remainingCount(int collected, int requested) {
    return requested < collected ? 0 : requested - collected;
  }

  /// Create a Record instance with class [classRef] from [remoteObject].
  ///
  /// Returns an instance containing [count] fields, if available,
  /// starting from the [offset].
  ///
  /// If [offset] is `null`, assumes 0 offset.
  /// If [count] is `null`, return all fields starting from the offset.
  /// [length] is the expected length of the whole object, read from
  /// the [ClassMetaData].
  Future<Instance?> _recordInstanceFor(
    ClassMetaData metaData,
    RemoteObject remoteObject, {
    int? offset,
    int? count,
  }) async {
    final objectId = remoteObject.objectId;
    if (objectId == null) return null;
    // Records are complicated, do an eval to get names and values.
    final fields =
        await _recordFields(remoteObject, offset: offset, count: count);
    final rangeCount = _calculateRangeCount(
      count: count,
      elementCount: fields.length,
      length: metaData.length,
    );
    return Instance(
      identityHashCode: remoteObject.objectId.hashCode,
      kind: InstanceKind.kRecord,
      id: objectId,
      classRef: metaData.classRef,
      length: metaData.length,
      offset: offset,
      count: rangeCount,
      fields: fields,
    );
  }

  /// Create a RecordType instance with class [classRef] from [remoteObject].
  ///
  /// Returns an instance containing [count] fields, if available,
  /// starting from the [offset].
  ///
  /// If [offset] is `null`, assumes 0 offset.
  /// If [count] is `null`, return all fields starting from the offset.
  /// [length] is the expected length of the whole object, read from
  /// the [ClassMetaData].
  Future<Instance?> _recordTypeInstanceFor(
    ClassMetaData metaData,
    RemoteObject remoteObject, {
    int? offset,
    int? count,
  }) async {
    final objectId = remoteObject.objectId;
    if (objectId == null) return null;

    // Records are complicated, do an eval to get names and values.
    final fields = await _recordTypeFields(
      remoteObject,
      offset: offset,
      count: count,
    );
    final rangeCount = _calculateRangeCount(
      count: count,
      elementCount: fields.length,
      length: metaData.length,
    );
    return Instance(
      identityHashCode: remoteObject.objectId.hashCode,
      kind: InstanceKind.kRecordType,
      id: objectId,
      classRef: metaData.classRef,
      length: metaData.length,
      offset: offset,
      count: rangeCount,
      fields: fields,
    );
  }

  /// The field types for a Dart RecordType.
  ///
  /// Returns a range of [count] field types, if available, starting from
  /// the [offset].
  ///
  /// If [offset] is `null`, assumes 0 offset.
  /// If [count] is `null`, return all field types starting from the offset.
  Future<List<BoundField>> _recordTypeFields(
    RemoteObject record, {
    int? offset,
    int? count,
  }) async {
    // We do this in in awkward way because we want the names and types, but we
    // can't return things by value or some Dart objects will come back as
    // values that we need to be RemoteObject, e.g. a List of int.
    final expression = _jsRuntimeFunctionCall('getRecordTypeFields(this)');

    final result = await inspector.jsCallFunctionOn(record, expression, []);
    final fieldNameElements =
        await _recordShapeFields(result, offset: offset, count: count);

    final typesObject = await inspector.loadField(result, 'types');
    final typesInstance =
        await instanceFor(typesObject, offset: offset, count: count);
    final typeElements = typesInstance?.elements ?? [];

    return _elementsToBoundFields(fieldNameElements, typeElements);
  }

  Future<Instance?> _setInstanceFor(
    ClassMetaData metaData,
    RemoteObject remoteObject, {
    int? offset,
    int? count,
  }) async {
    final length = metaData.length;
    final objectId = remoteObject.objectId;
    if (objectId == null) return null;

    final expression = _jsRuntimeFunctionCall('getSetElements(this)');

    final result =
        await inspector.jsCallFunctionOn(remoteObject, expression, []);
    final entriesObject = await inspector.loadField(result, 'entries');
    final entriesInstance =
        await instanceFor(entriesObject, offset: offset, count: count);
    final elements = entriesInstance?.elements ?? [];

    final setInstance = Instance(
      identityHashCode: remoteObject.objectId.hashCode,
      kind: InstanceKind.kSet,
      id: objectId,
      classRef: metaData.classRef,
      length: length,
      elements: elements,
    );

    if (offset != null && offset > 0) {
      setInstance.offset = offset;
    }
    if (length != null && elements.length < length) {
      setInstance.count = elements.length;
    }

    return setInstance;
  }

  /// Create Type instance with class [classRef] from [remoteObject].
  ///
  /// Collect information from the internal [remoteObject] and present
  /// it as an instance of [Type] class.
  ///
  /// Returns an instance containing `hashCode` and `runtimeType` fields.
  /// [length] is the expected length of the whole object, read from
  /// the [ClassMetaData].
  Future<Instance?> _plainTypeInstanceFor(
    ClassMetaData metaData,
    RemoteObject remoteObject, {
    int? offset,
    int? count,
  }) async {
    final objectId = remoteObject.objectId;
    if (objectId == null) return null;

    final fields = await _typeFields(metaData.classRef, remoteObject);
    return Instance(
      identityHashCode: objectId.hashCode,
      kind: InstanceKind.kType,
      id: objectId,
      classRef: metaData.classRef,
      name: metaData.typeName,
      length: metaData.length,
      offset: offset,
      count: count,
      fields: fields,
    );
  }

  /// The field types for a Dart RecordType.
  ///
  /// Returns a range of [count] field types, if available, starting from
  /// the [offset].
  ///
  /// If [offset] is `null`, assumes 0 offset.
  /// If [count] is `null`, return all field types starting from the offset.
  Future<List<BoundField>> _typeFields(
    ClassRef classRef,
    RemoteObject type,
  ) async {
    // Present the type as an instance of `core.Type` class and
    // hide the internal implementation.
    final expression = _jsRuntimeFunctionCall('getTypeFields(this)');

    final result = await inspector.jsCallFunctionOn(type, expression, []);
    final hashCodeObject = await inspector.loadField(result, 'hashCode');
    final runtimeTypeObject = await inspector.loadField(result, 'runtimeType');

    final properties = [
      Property({'name': 'hashCode', 'value': hashCodeObject}),
      Property({'name': 'runtimeType', 'value': runtimeTypeObject}),
    ];

    final boundFields = await Future.wait(
      properties.map<Future<BoundField>>((p) => _fieldFor(p, classRef)),
    );
    return boundFields;
  }

  /// Return the available count of elements in the requested range.
  /// Return `null` if the range includes the whole object.
  /// [count] is the range length requested by the `getObject` call.
  /// [elementCount] is the number of elements in the runtime object.
  /// [length] is the expected length of the whole object, read from
  /// the [ClassMetaData].
  static int? _calculateRangeCount({
    int? count,
    int? elementCount,
    int? length,
  }) {
    if (count == null) return null;
    if (elementCount == null) return null;
    if (length == elementCount) return null;
    return min(count, elementCount);
  }

  /// Filter [allJsProperties] and return a list containing only those
  /// that correspond to Dart fields on [remoteObject].
  ///
  /// This only applies to objects with named fields, not Lists or Maps.
  Future<List<Property>> _dartFieldsFor(
    List<Property> allJsProperties,
    RemoteObject remoteObject,
  ) async {
    // An expression to find the field names from the types, extract both
    // private (named by symbols) and public (named by strings) and return them
    // as a comma-separated single string, so we can return it by value and not
    // need to make multiple round trips.
    //
    // For maps and lists it's more complicated. Treat the actual SDK versions
    // of these as special.
    final fieldNameExpression =
        _jsRuntimeFunctionCall('getObjectFieldNames(this)');

    final result = await inspector.jsCallFunctionOn(
      remoteObject,
      fieldNameExpression,
      [],
      returnByValue: true,
    );
    final names = List<String>.from(result.value as List);
    // TODO(#761): Better support for large collections.
    return allJsProperties
        .where((property) => names.contains(property.name))
        .toList();
  }

  /// Create an InstanceRef for an object, which may be a RemoteObject, or may
  /// be something returned by value from Chrome, e.g. number, boolean, or
  /// String.
  Future<InstanceRef?> instanceRefFor(Object value) {
    final remote = value is RemoteObject
        ? value
        : RemoteObject({'value': value, 'type': _chromeType(value)});
    return _instanceRefForRemote(remote);
  }

  /// The Chrome type for a value.
  String? _chromeType(Object? value) {
    if (value == null) return null;
    if (value is String) return 'string';
    if (value is num) return 'number';
    if (value is bool) return 'boolean';
    if (value is Function) return 'function';
    return 'object';
  }

  /// Create an [InstanceRef] for the given Chrome [remoteObject].
  Future<InstanceRef?> _instanceRefForRemote(RemoteObject? remoteObject) async {
    // If we have a null result, treat it as a reference to null.
    if (remoteObject == null) {
      return kNullInstanceRef;
    }

    switch (remoteObject.type) {
      case 'string':
        final stringValue = remoteObject.value as String?;
        // TODO: Support truncation for long strings.
        // TODO(#777): dartIdFor() will return an ID containing the entire
        // string, even if we're truncating the string value here.
        return InstanceRef(
          identityHashCode: dartIdFor(remoteObject.value).hashCode,
          id: dartIdFor(remoteObject.value),
          classRef: classRefForString,
          kind: InstanceKind.kString,
          valueAsString: stringValue,
          length: stringValue?.length,
        );
      case 'number':
        return _primitiveInstanceRef(InstanceKind.kDouble, remoteObject);
      case 'boolean':
        return _primitiveInstanceRef(InstanceKind.kBool, remoteObject);
      case 'undefined':
        return _primitiveInstanceRef(InstanceKind.kNull, remoteObject);
      case 'object':
        final objectId = remoteObject.objectId;
        if (objectId == null) {
          return _primitiveInstanceRef(InstanceKind.kNull, remoteObject);
        }
        final metaData = await metadataHelper.metaDataFor(remoteObject);
        if (metaData == null) return null;

        return InstanceRef(
          kind: metaData.kind,
          id: objectId,
          identityHashCode: objectId.hashCode,
          classRef: metaData.classRef,
          length: metaData.length,
          name: metaData.typeName,
        );
      case 'function':
        final objectId = remoteObject.objectId;
        if (objectId == null) {
          return _primitiveInstanceRef(InstanceKind.kNull, remoteObject);
        }
        final functionMetaData = await FunctionMetaData.metaDataFor(
          inspector.remoteDebugger,
          remoteObject,
        );
        // TODO(annagrin) - fill missing information.
        // https://github.com/dart-lang/sdk/issues/46723
        return InstanceRef(
          kind: InstanceKind.kClosure,
          id: objectId,
          identityHashCode: objectId.hashCode,
          classRef: classRefForClosure,
          closureFunction: FuncRef(
            name: functionMetaData.name,
            id: createId(),
            owner: classRefForUnknown,
            isConst: false,
            isStatic: false,
            implicit: false,
            isGetter: false,
            isSetter: false,
          ),
          closureContext: ContextRef(length: 0, id: createId()),
        );
      default:
        // Return null for an unsupported type. This is likely a JS construct.
        return null;
    }
  }
}

String _jsRuntimeFunctionCall(String expression) => '''
  function() {
    const sdk = ${globalToolConfiguration.loadStrategy.loadModuleSnippet}('dart_sdk');
    const dart = sdk.dart;
    return dart.$expression;
  }
''';
