// 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:
        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.kind != InstanceKind.kPlainInstance
          ? metaData.length
          : null,
    );

    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 = globalToolConfiguration.loadStrategy.dartRuntimeDebugger
        .getMapElementsJsExpression();

    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 = globalToolConfiguration.loadStrategy.dartRuntimeDebugger
        .getRecordFieldsJsExpression();

    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 = globalToolConfiguration.loadStrategy.dartRuntimeDebugger
        .getRecordTypeFieldsJsExpression();

    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 = globalToolConfiguration.loadStrategy.dartRuntimeDebugger
        .getSetElementsJsExpression();

    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 = globalToolConfiguration
        .loadStrategy
        .dartRuntimeDebugger
        .getObjectFieldNamesJsExpression();
    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;
    }
  }
}
