// 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 fields = await _getInstanceFields(
      metaData,
      remoteObject,
      offset: offset,
      count: count,
    );

    final result = Instance(
      kind: InstanceKind.kPlainInstance,
      id: objectId,
      identityHashCode: remoteObject.objectId.hashCode,
      classRef: metaData.classRef,
      fields: fields,
    );
    return result;
  }

  Future<List<BoundField>> _getInstanceFields(
    ClassMetaData metaData,
    RemoteObject remoteObject, {
    int? offset,
    int? count,
  }) async {
    final objectId = remoteObject.objectId;
    if (objectId == null) throw StateError('Object id is null for instance');

    final properties = await inspector.getProperties(
      objectId,
      offset: offset,
      count: count,
      length: metaData.length,
    );

    final dartProperties = await _dartFieldsFor(properties, remoteObject);
    final boundFields = await Future.wait(
      dartProperties
          .map<Future<BoundField>>((p) => _fieldFor(p, metaData.classRef)),
    );

    return boundFields
        .where((bv) => inspector.isDisplayableObject(bv.value))
        .toList()
      ..sort(_compareBoundFields);
  }

  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 _getInstanceFields(
      metaData,
      remoteObject,
      offset: offset,
      count: count,
    );

    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,
    );
  }

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