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

/// Defines the objects used for communication between the macro executor and
/// the isolate or process doing the work of macro loading and execution.
library _fe_analyzer_shared.src.macros.executor_shared.protocol;

import 'package:meta/meta.dart';

import '../executor.dart';
import '../api.dart';
import '../executor/response_impls.dart';
import 'introspection_impls.dart';
import 'remote_instance.dart';
import 'serialization.dart';
import 'serialization_extensions.dart';

/// Base class all requests extend, provides a unique id for each request.
abstract class Request implements Serializable {
  final int id;

  final int serializationZoneId;

  Request({int? id, required this.serializationZoneId})
      : this.id = id ?? _next++;

  /// The [serializationZoneId] is a part of the header and needs to be parsed
  /// before deserializing objects, and then passed in here.
  Request.deserialize(Deserializer deserializer, this.serializationZoneId)
      : id = (deserializer..moveNext()).expectInt();

  /// The [serializationZoneId] needs to be separately serialized before the
  /// rest of the object. This is not done by the instances themselves but by
  /// the macro implementations.
  @mustCallSuper
  void serialize(Serializer serializer) => serializer.addInt(id);

  static int _next = 0;
}

/// A generic response object that contains either a response or an error, and
/// a unique ID.
class Response {
  final Object? response;
  final Object? error;
  final String? stackTrace;
  final int requestId;
  final MessageType responseType;

  Response({
    this.response,
    this.error,
    this.stackTrace,
    required this.requestId,
    required this.responseType,
  })  : assert(response != null || error != null),
        assert(response == null || error == null);
}

/// A serializable [Response], contains the message type as an enum.
class SerializableResponse implements Response, Serializable {
  final Serializable? response;
  final MessageType responseType;
  final String? error;
  final String? stackTrace;
  final int requestId;
  final int serializationZoneId;

  SerializableResponse({
    this.error,
    this.stackTrace,
    required this.requestId,
    this.response,
    required this.responseType,
    required this.serializationZoneId,
  });

  /// You must first parse the [serializationZoneId] yourself, and then
  /// call this function in that zone, and pass the ID.
  factory SerializableResponse.deserialize(
      Deserializer deserializer, int serializationZoneId) {
    deserializer.moveNext();
    MessageType responseType = MessageType.values[deserializer.expectInt()];
    Serializable? response;
    String? error;
    String? stackTrace;
    switch (responseType) {
      case MessageType.error:
        deserializer.moveNext();
        error = deserializer.expectString();
        deserializer.moveNext();
        stackTrace = deserializer.expectNullableString();
        break;
      case MessageType.argumentError:
        deserializer.moveNext();
        error = deserializer.expectString();
        break;
      case MessageType.macroClassIdentifier:
        response = new MacroClassIdentifierImpl.deserialize(deserializer);
        break;
      case MessageType.macroInstanceIdentifier:
        response = new MacroInstanceIdentifierImpl.deserialize(deserializer);
        break;
      case MessageType.macroExecutionResult:
        response = new MacroExecutionResultImpl.deserialize(deserializer);
        break;
      case MessageType.staticType:
      case MessageType.namedStaticType:
        response = RemoteInstance.deserialize(deserializer);
        break;
      case MessageType.boolean:
        response = new BooleanValue.deserialize(deserializer);
        break;
      case MessageType.declarationList:
        response = new DeclarationList.deserialize(deserializer);
        break;
      case MessageType.remoteInstance:
        deserializer.moveNext();
        if (!deserializer.checkNull()) {
          response = deserializer.expectRemoteInstance();
        }
        break;
      default:
        throw new StateError('Unexpected response type $responseType');
    }

    return new SerializableResponse(
        responseType: responseType,
        response: response,
        error: error,
        stackTrace: stackTrace,
        requestId: (deserializer..moveNext()).expectInt(),
        serializationZoneId: serializationZoneId);
  }

  void serialize(Serializer serializer) {
    serializer
      ..addInt(serializationZoneId)
      ..addInt(MessageType.response.index)
      ..addInt(responseType.index);
    switch (responseType) {
      case MessageType.error:
        serializer.addString(error!.toString());
        serializer.addNullableString(stackTrace);
        break;
      case MessageType.argumentError:
        serializer.addString(error!.toString());
        break;
      default:
        response.serializeNullable(serializer);
    }
    serializer.addInt(requestId);
  }
}

class BooleanValue implements Serializable {
  final bool value;

  BooleanValue(this.value);

  BooleanValue.deserialize(Deserializer deserializer)
      : value = (deserializer..moveNext()).expectBool();

  @override
  void serialize(Serializer serializer) => serializer..addBool(value);
}

/// A serialized list of [Declaration]s.
class DeclarationList<T extends DeclarationImpl> implements Serializable {
  final List<T> declarations;

  DeclarationList(this.declarations);

  DeclarationList.deserialize(Deserializer deserializer)
      : declarations = [
          for (bool hasNext = (deserializer
                    ..moveNext()
                    ..expectList())
                  .moveNext();
              hasNext;
              hasNext = deserializer.moveNext())
            deserializer.expectRemoteInstance(),
        ];

  @override
  void serialize(Serializer serializer) {
    serializer.startList();
    for (DeclarationImpl declaration in declarations) {
      declaration.serialize(serializer);
    }
    serializer.endList();
  }
}

/// A request to load a macro in this isolate.
class LoadMacroRequest extends Request {
  final Uri library;
  final String name;

  LoadMacroRequest(this.library, this.name, {required int serializationZoneId})
      : super(serializationZoneId: serializationZoneId);

  LoadMacroRequest.deserialize(
      Deserializer deserializer, int serializationZoneId)
      : library = Uri.parse((deserializer..moveNext()).expectString()),
        name = (deserializer..moveNext()).expectString(),
        super.deserialize(deserializer, serializationZoneId);

  @override
  void serialize(Serializer serializer) {
    serializer
      ..addInt(MessageType.loadMacroRequest.index)
      ..addString(library.toString())
      ..addString(name);
    super.serialize(serializer);
  }
}

/// A request to instantiate a macro instance.
class InstantiateMacroRequest extends Request {
  final MacroClassIdentifier macroClass;
  final String constructorName;
  final Arguments arguments;

  /// The ID to assign to the identifier, this needs to come from the requesting
  /// side so that it is unique.
  final int instanceId;

  InstantiateMacroRequest(
      this.macroClass, this.constructorName, this.arguments, this.instanceId,
      {required int serializationZoneId})
      : super(serializationZoneId: serializationZoneId);

  InstantiateMacroRequest.deserialize(
      Deserializer deserializer, int serializationZoneId)
      : macroClass = new MacroClassIdentifierImpl.deserialize(deserializer),
        constructorName = (deserializer..moveNext()).expectString(),
        arguments = new Arguments.deserialize(deserializer),
        instanceId = (deserializer..moveNext()).expectInt(),
        super.deserialize(deserializer, serializationZoneId);

  @override
  void serialize(Serializer serializer) {
    serializer.addInt(MessageType.instantiateMacroRequest.index);
    macroClass.serialize(serializer);
    serializer.addString(constructorName);
    arguments.serialize(serializer);
    serializer.addInt(instanceId);
    super.serialize(serializer);
  }
}

/// A request to execute a macro on a particular declaration in the types phase.
class ExecuteTypesPhaseRequest extends Request {
  final MacroInstanceIdentifier macro;
  final DeclarationImpl declaration;
  final RemoteInstanceImpl identifierResolver;

  ExecuteTypesPhaseRequest(
      this.macro, this.declaration, this.identifierResolver,
      {required int serializationZoneId})
      : super(serializationZoneId: serializationZoneId);

  /// When deserializing we have already consumed the message type, so we don't
  /// consume it again.
  ExecuteTypesPhaseRequest.deserialize(
      Deserializer deserializer, int serializationZoneId)
      : macro = new MacroInstanceIdentifierImpl.deserialize(deserializer),
        declaration = RemoteInstance.deserialize(deserializer),
        identifierResolver = RemoteInstance.deserialize(deserializer),
        super.deserialize(deserializer, serializationZoneId);

  void serialize(Serializer serializer) {
    serializer.addInt(MessageType.executeTypesPhaseRequest.index);
    macro.serialize(serializer);
    declaration.serialize(serializer);
    identifierResolver.serialize(serializer);

    super.serialize(serializer);
  }
}

/// A request to execute a macro on a particular declaration in the definition
/// phase.
class ExecuteDeclarationsPhaseRequest extends Request {
  final MacroInstanceIdentifier macro;
  final DeclarationImpl declaration;

  final RemoteInstanceImpl identifierResolver;
  final RemoteInstanceImpl typeResolver;
  final RemoteInstanceImpl classIntrospector;

  ExecuteDeclarationsPhaseRequest(this.macro, this.declaration,
      this.identifierResolver, this.typeResolver, this.classIntrospector,
      {required int serializationZoneId})
      : super(serializationZoneId: serializationZoneId);

  /// When deserializing we have already consumed the message type, so we don't
  /// consume it again.
  ExecuteDeclarationsPhaseRequest.deserialize(
      Deserializer deserializer, int serializationZoneId)
      : macro = new MacroInstanceIdentifierImpl.deserialize(deserializer),
        declaration = RemoteInstance.deserialize(deserializer),
        identifierResolver = RemoteInstance.deserialize(deserializer),
        typeResolver = RemoteInstance.deserialize(deserializer),
        classIntrospector = RemoteInstance.deserialize(deserializer),
        super.deserialize(deserializer, serializationZoneId);

  void serialize(Serializer serializer) {
    serializer.addInt(MessageType.executeDeclarationsPhaseRequest.index);
    macro.serialize(serializer);
    declaration.serialize(serializer);
    identifierResolver.serialize(serializer);
    typeResolver.serialize(serializer);
    classIntrospector.serialize(serializer);

    super.serialize(serializer);
  }
}

/// A request to execute a macro on a particular declaration in the definition
/// phase.
class ExecuteDefinitionsPhaseRequest extends Request {
  final MacroInstanceIdentifier macro;
  final DeclarationImpl declaration;

  final RemoteInstanceImpl identifierResolver;
  final RemoteInstanceImpl typeResolver;
  final RemoteInstanceImpl classIntrospector;
  final RemoteInstanceImpl typeDeclarationResolver;
  final RemoteInstanceImpl typeInferrer;

  ExecuteDefinitionsPhaseRequest(
      this.macro,
      this.declaration,
      this.identifierResolver,
      this.typeResolver,
      this.classIntrospector,
      this.typeDeclarationResolver,
      this.typeInferrer,
      {required int serializationZoneId})
      : super(serializationZoneId: serializationZoneId);

  /// When deserializing we have already consumed the message type, so we don't
  /// consume it again.
  ExecuteDefinitionsPhaseRequest.deserialize(
      Deserializer deserializer, int serializationZoneId)
      : macro = new MacroInstanceIdentifierImpl.deserialize(deserializer),
        declaration = RemoteInstance.deserialize(deserializer),
        identifierResolver = RemoteInstance.deserialize(deserializer),
        typeResolver = RemoteInstance.deserialize(deserializer),
        classIntrospector = RemoteInstance.deserialize(deserializer),
        typeDeclarationResolver = RemoteInstance.deserialize(deserializer),
        typeInferrer = RemoteInstance.deserialize(deserializer),
        super.deserialize(deserializer, serializationZoneId);

  void serialize(Serializer serializer) {
    serializer.addInt(MessageType.executeDefinitionsPhaseRequest.index);
    macro.serialize(serializer);
    declaration.serialize(serializer);
    identifierResolver.serialize(serializer);
    typeResolver.serialize(serializer);
    classIntrospector.serialize(serializer);
    typeDeclarationResolver.serialize(serializer);
    typeInferrer.serialize(serializer);

    super.serialize(serializer);
  }
}

/// A request to create a resolved identifier.
class ResolveIdentifierRequest extends Request {
  final Uri library;
  final String name;

  final RemoteInstanceImpl identifierResolver;

  /// When deserializing we have already consumed the message type, so we don't
  /// consume it again.
  ResolveIdentifierRequest(this.library, this.name, this.identifierResolver,
      {required int serializationZoneId})
      : super(serializationZoneId: serializationZoneId);

  ResolveIdentifierRequest.deserialize(
      Deserializer deserializer, int serializationZoneId)
      : library = Uri.parse((deserializer..moveNext()).expectString()),
        name = (deserializer..moveNext()).expectString(),
        identifierResolver = RemoteInstance.deserialize(deserializer),
        super.deserialize(deserializer, serializationZoneId);

  void serialize(Serializer serializer) {
    serializer
      ..addInt(MessageType.resolveIdentifierRequest.index)
      ..addString(library.toString())
      ..addString(name);
    identifierResolver.serialize(serializer);

    super.serialize(serializer);
  }
}

/// A request to resolve on a type annotation code object
class ResolveTypeRequest extends Request {
  final TypeAnnotationCode typeAnnotationCode;
  final RemoteInstanceImpl typeResolver;

  ResolveTypeRequest(this.typeAnnotationCode, this.typeResolver,
      {required int serializationZoneId})
      : super(serializationZoneId: serializationZoneId);

  /// When deserializing we have already consumed the message type, so we don't
  /// consume it again.
  ResolveTypeRequest.deserialize(
      Deserializer deserializer, int serializationZoneId)
      : typeAnnotationCode = (deserializer..moveNext()).expectCode(),
        typeResolver = RemoteInstance.deserialize(deserializer),
        super.deserialize(deserializer, serializationZoneId);

  void serialize(Serializer serializer) {
    serializer.addInt(MessageType.resolveTypeRequest.index);
    typeAnnotationCode.serialize(serializer);
    typeResolver.serialize(serializer);
    super.serialize(serializer);
  }
}

/// A request to check if a type is exactly another type.
class IsExactlyTypeRequest extends Request {
  final RemoteInstanceImpl leftType;
  final RemoteInstanceImpl rightType;

  IsExactlyTypeRequest(this.leftType, this.rightType,
      {required int serializationZoneId})
      : super(serializationZoneId: serializationZoneId);

  /// When deserializing we have already consumed the message type, so we don't
  /// consume it again.
  IsExactlyTypeRequest.deserialize(
      Deserializer deserializer, int serializationZoneId)
      : leftType = RemoteInstance.deserialize(deserializer),
        rightType = RemoteInstance.deserialize(deserializer),
        super.deserialize(deserializer, serializationZoneId);

  void serialize(Serializer serializer) {
    serializer.addInt(MessageType.isExactlyTypeRequest.index);
    leftType.serialize(serializer);
    rightType.serialize(serializer);
    super.serialize(serializer);
  }
}

/// A request to check if a type is exactly another type.
class IsSubtypeOfRequest extends Request {
  final RemoteInstanceImpl leftType;
  final RemoteInstanceImpl rightType;

  IsSubtypeOfRequest(this.leftType, this.rightType,
      {required int serializationZoneId})
      : super(serializationZoneId: serializationZoneId);

  /// When deserializing we have already consumed the message type, so we don't
  /// consume it again.
  IsSubtypeOfRequest.deserialize(
      Deserializer deserializer, int serializationZoneId)
      : leftType = RemoteInstance.deserialize(deserializer),
        rightType = RemoteInstance.deserialize(deserializer),
        super.deserialize(deserializer, serializationZoneId);

  void serialize(Serializer serializer) {
    serializer.addInt(MessageType.isSubtypeOfRequest.index);
    leftType.serialize(serializer);
    rightType.serialize(serializer);
    super.serialize(serializer);
  }
}

/// A general request class for all requests coming from methods on the
/// [ClassIntrospector] interface.
class ClassIntrospectionRequest extends Request {
  final ClassDeclarationImpl classDeclaration;
  final RemoteInstanceImpl classIntrospector;
  final MessageType requestKind;

  ClassIntrospectionRequest(
      this.classDeclaration, this.classIntrospector, this.requestKind,
      {required int serializationZoneId})
      : super(serializationZoneId: serializationZoneId);

  /// When deserializing we have already consumed the message type, so we don't
  /// consume it again and it should instead be passed in here.
  ClassIntrospectionRequest.deserialize(
      Deserializer deserializer, this.requestKind, int serializationZoneId)
      : classDeclaration = RemoteInstance.deserialize(deserializer),
        classIntrospector = RemoteInstance.deserialize(deserializer),
        super.deserialize(deserializer, serializationZoneId);

  @override
  void serialize(Serializer serializer) {
    serializer.addInt(requestKind.index);
    classDeclaration.serialize(serializer);
    classIntrospector.serialize(serializer);
    super.serialize(serializer);
  }
}

/// A request to get a [TypeDeclaration] for a [StaticType].
class DeclarationOfRequest extends Request {
  final IdentifierImpl identifier;
  final RemoteInstanceImpl typeDeclarationResolver;

  DeclarationOfRequest(this.identifier, this.typeDeclarationResolver,
      {required int serializationZoneId})
      : super(serializationZoneId: serializationZoneId);

  /// When deserializing we have already consumed the message type, so we don't
  /// consume it again.
  DeclarationOfRequest.deserialize(
      Deserializer deserializer, int serializationZoneId)
      : identifier = RemoteInstance.deserialize(deserializer),
        typeDeclarationResolver = RemoteInstance.deserialize(deserializer),
        super.deserialize(deserializer, serializationZoneId);

  @override
  void serialize(Serializer serializer) {
    serializer.addInt(MessageType.declarationOfRequest.index);
    identifier.serialize(serializer);
    typeDeclarationResolver.serialize(serializer);
    super.serialize(serializer);
  }
}

/// A request to get an inferred [TypeAnnotation] for an
/// [OmittedTypeAnnotation].
class InferTypeRequest extends Request {
  final OmittedTypeAnnotationImpl omittedType;
  final RemoteInstanceImpl typeInferrer;

  InferTypeRequest(this.omittedType, this.typeInferrer,
      {required int serializationZoneId})
      : super(serializationZoneId: serializationZoneId);

  /// When deserializing we have already consumed the message type, so we don't
  /// consume it again.
  InferTypeRequest.deserialize(
      Deserializer deserializer, int serializationZoneId)
      : omittedType = RemoteInstance.deserialize(deserializer),
        typeInferrer = RemoteInstance.deserialize(deserializer),
        super.deserialize(deserializer, serializationZoneId);

  @override
  void serialize(Serializer serializer) {
    serializer.addInt(MessageType.inferTypeRequest.index);
    omittedType.serialize(serializer);
    typeInferrer.serialize(serializer);
    super.serialize(serializer);
  }
}

/// Client side implementation of an [IdentifierResolver], which creates a
/// [ResolveIdentifierRequest] and passes it to a given [_sendRequest] function
/// which can return the [Response].
class ClientIdentifierResolver implements IdentifierResolver {
  /// The actual remote instance of this type resolver.
  final RemoteInstanceImpl remoteInstance;

  /// The ID of the zone in which to find the original type resolver.
  final int serializationZoneId;

  /// A function that can send a request and return a response using an
  /// arbitrary communication channel.
  final Future<Response> Function(Request request) _sendRequest;

  ClientIdentifierResolver(this._sendRequest,
      {required this.remoteInstance, required this.serializationZoneId});

  @override
  Future<Identifier> resolveIdentifier(Uri library, String name) async {
    ResolveIdentifierRequest request = new ResolveIdentifierRequest(
        library, name, remoteInstance,
        serializationZoneId: serializationZoneId);
    return _handleResponse(await _sendRequest(request));
  }
}

/// Client side implementation of a [TypeResolver], which creates a
/// [ResolveTypeRequest] and passes it to a given [sendRequest] function which
/// can return the [Response].
class ClientTypeResolver implements TypeResolver {
  /// The actual remote instance of this type resolver.
  final RemoteInstanceImpl remoteInstance;

  /// The ID of the zone in which to find the original type resolver.
  final int serializationZoneId;

  /// A function that can send a request and return a response using an
  /// arbitrary communication channel.
  final Future<Response> Function(Request request) _sendRequest;

  ClientTypeResolver(this._sendRequest,
      {required this.remoteInstance, required this.serializationZoneId});

  @override
  Future<StaticType> resolve(TypeAnnotationCode typeAnnotation) async {
    ResolveTypeRequest request = new ResolveTypeRequest(
        typeAnnotation, remoteInstance,
        serializationZoneId: serializationZoneId);
    RemoteInstanceImpl remoteType =
        _handleResponse(await _sendRequest(request));
    switch (remoteType.kind) {
      case RemoteInstanceKind.namedStaticType:
        return new ClientNamedStaticTypeImpl(_sendRequest,
            remoteInstance: remoteType,
            serializationZoneId: serializationZoneId);
      case RemoteInstanceKind.staticType:
        return new ClientStaticTypeImpl(_sendRequest,
            remoteInstance: remoteType,
            serializationZoneId: serializationZoneId);
      default:
        throw new StateError(
            'Expected either a StaticType or NamedStaticType but got '
            '${remoteType.kind}');
    }
  }
}

class ClientStaticTypeImpl implements StaticType {
  /// The actual remote instance of this static type.
  final RemoteInstanceImpl remoteInstance;

  final int serializationZoneId;

  /// A function that can send a request and return a response using an
  /// arbitrary communication channel.
  final Future<Response> Function(Request request) sendRequest;

  ClientStaticTypeImpl(this.sendRequest,
      {required this.remoteInstance, required this.serializationZoneId});

  @override
  Future<bool> isExactly(ClientStaticTypeImpl other) async {
    IsExactlyTypeRequest request = new IsExactlyTypeRequest(
        this.remoteInstance, other.remoteInstance,
        serializationZoneId: serializationZoneId);
    return _handleResponse<BooleanValue>(await sendRequest(request)).value;
  }

  @override
  Future<bool> isSubtypeOf(ClientStaticTypeImpl other) async {
    IsSubtypeOfRequest request = new IsSubtypeOfRequest(
        remoteInstance, other.remoteInstance,
        serializationZoneId: serializationZoneId);
    return _handleResponse<BooleanValue>(await sendRequest(request)).value;
  }
}

/// Named variant of the [ClientStaticTypeImpl].
class ClientNamedStaticTypeImpl extends ClientStaticTypeImpl
    implements NamedStaticType {
  ClientNamedStaticTypeImpl(
      Future<Response> Function(Request request) sendRequest,
      {required RemoteInstanceImpl remoteInstance,
      required int serializationZoneId})
      : super(sendRequest,
            remoteInstance: remoteInstance,
            serializationZoneId: serializationZoneId);
}

/// Client side implementation of the [ClientClassIntrospector], converts all
/// invocations into remote RPC calls.
class ClientClassIntrospector implements ClassIntrospector {
  /// The actual remote instance of this class introspector.
  final RemoteInstanceImpl remoteInstance;

  /// The ID of the zone in which to find the original type resolver.
  final int serializationZoneId;

  /// A function that can send a request and return a response using an
  /// arbitrary communication channel.
  final Future<Response> Function(Request request) sendRequest;

  ClientClassIntrospector(this.sendRequest,
      {required this.remoteInstance, required this.serializationZoneId});

  @override
  Future<List<ConstructorDeclaration>> constructorsOf(
      ClassDeclarationImpl clazz) async {
    ClassIntrospectionRequest request = new ClassIntrospectionRequest(
        clazz, remoteInstance, MessageType.constructorsOfRequest,
        serializationZoneId: serializationZoneId);
    return _handleResponse<DeclarationList>(await sendRequest(request))
        .declarations
        // TODO: Refactor so we can remove this cast
        .cast();
  }

  @override
  Future<List<FieldDeclaration>> fieldsOf(ClassDeclarationImpl clazz) async {
    ClassIntrospectionRequest request = new ClassIntrospectionRequest(
        clazz, remoteInstance, MessageType.fieldsOfRequest,
        serializationZoneId: serializationZoneId);
    return _handleResponse<DeclarationList>(await sendRequest(request))
        .declarations
        // TODO: Refactor so we can remove this cast
        .cast();
  }

  @override
  Future<List<ClassDeclaration>> interfacesOf(
      ClassDeclarationImpl clazz) async {
    ClassIntrospectionRequest request = new ClassIntrospectionRequest(
        clazz, remoteInstance, MessageType.interfacesOfRequest,
        serializationZoneId: serializationZoneId);
    return _handleResponse<DeclarationList>(await sendRequest(request))
        .declarations
        // TODO: Refactor so we can remove this cast
        .cast();
  }

  @override
  Future<List<MethodDeclaration>> methodsOf(ClassDeclarationImpl clazz) async {
    ClassIntrospectionRequest request = new ClassIntrospectionRequest(
        clazz, remoteInstance, MessageType.methodsOfRequest,
        serializationZoneId: serializationZoneId);
    return _handleResponse<DeclarationList>(await sendRequest(request))
        .declarations
        // TODO: Refactor so we can remove this cast
        .cast();
  }

  @override
  Future<List<ClassDeclaration>> mixinsOf(ClassDeclarationImpl clazz) async {
    ClassIntrospectionRequest request = new ClassIntrospectionRequest(
        clazz, remoteInstance, MessageType.mixinsOfRequest,
        serializationZoneId: serializationZoneId);
    return _handleResponse<DeclarationList>(await sendRequest(request))
        .declarations
        // TODO: Refactor so we can remove this cast
        .cast();
  }

  @override
  Future<ClassDeclaration?> superclassOf(ClassDeclarationImpl clazz) async {
    ClassIntrospectionRequest request = new ClassIntrospectionRequest(
        clazz, remoteInstance, MessageType.superclassOfRequest,
        serializationZoneId: serializationZoneId);
    return _handleResponse<ClassDeclaration?>(await sendRequest(request));
  }
}

/// Client side implementation of a [TypeDeclarationResolver], converts all
/// invocations into remote procedure calls.
class ClientTypeDeclarationResolver implements TypeDeclarationResolver {
  /// The actual remote instance of this type resolver.
  final RemoteInstanceImpl remoteInstance;

  /// The ID of the zone in which to find the original type resolver.
  final int serializationZoneId;

  /// A function that can send a request and return a response using an
  /// arbitrary communication channel.
  final Future<Response> Function(Request request) sendRequest;

  ClientTypeDeclarationResolver(this.sendRequest,
      {required this.remoteInstance, required this.serializationZoneId});

  @override
  Future<TypeDeclaration> declarationOf(IdentifierImpl identifier) async {
    DeclarationOfRequest request = new DeclarationOfRequest(
        identifier, remoteInstance,
        serializationZoneId: serializationZoneId);
    return _handleResponse<TypeDeclaration>(await sendRequest(request));
  }
}

/// Client side implementation of a [TypeInferrer], converts all
/// invocations into remote procedure calls.
class ClientTypeInferrer implements TypeInferrer {
  /// The actual remote instance of this type resolver.
  final RemoteInstanceImpl remoteInstance;

  /// The ID of the zone in which to find the original type resolver.
  final int serializationZoneId;

  /// A function that can send a request and return a response using an
  /// arbitrary communication channel.
  final Future<Response> Function(Request request) sendRequest;

  ClientTypeInferrer(this.sendRequest,
      {required this.remoteInstance, required this.serializationZoneId});

  @override
  Future<TypeAnnotation> inferType(
      OmittedTypeAnnotationImpl omittedType) async {
    InferTypeRequest request = new InferTypeRequest(omittedType, remoteInstance,
        serializationZoneId: serializationZoneId);
    return _handleResponse<TypeAnnotation>(await sendRequest(request));
  }
}

/// An exception that occurred remotely, the exception object and stack trace
/// are serialized as [String]s and both included in the [toString] output.
class RemoteException implements Exception {
  final String error;
  final String? stackTrace;

  RemoteException(this.error, [this.stackTrace]);

  String toString() =>
      'RemoteException: $error${stackTrace == null ? '' : '\n\n$stackTrace'}';
}

/// Either returns the actual response from [response], casted to [T], or throws
/// a [RemoteException] with the given error and stack trace.
T _handleResponse<T>(Response response) {
  if (response.responseType == MessageType.error) {
    throw new RemoteException(response.error!.toString(), response.stackTrace);
  } else if (response.responseType == MessageType.argumentError) {
    throw new ArgumentError(response.error!.toString());
  }

  return response.response as T;
}

enum MessageType {
  argumentError,
  boolean,
  constructorsOfRequest,
  declarationOfRequest,
  declarationList,
  fieldsOfRequest,
  interfacesOfRequest,
  methodsOfRequest,
  mixinsOfRequest,
  superclassOfRequest,
  error,
  executeDeclarationsPhaseRequest,
  executeDefinitionsPhaseRequest,
  executeTypesPhaseRequest,
  instantiateMacroRequest,
  resolveIdentifierRequest,
  resolveTypeRequest,
  inferTypeRequest,
  isExactlyTypeRequest,
  isSubtypeOfRequest,
  loadMacroRequest,
  remoteInstance,
  macroClassIdentifier,
  macroInstanceIdentifier,
  macroExecutionResult,
  namedStaticType,
  response,
  staticType,
}
