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

part of dart.developer;

/// A response to a service protocol extension RPC.
///
/// If the RPC was successful, use [ServiceExtensionResponse.result], otherwise
/// use [ServiceExtensionResponse.error].
final class ServiceExtensionResponse {
  /// The result of a successful service protocol extension RPC.
  final String? result;

  /// The error code associated with a failed service protocol extension RPC.
  final int? errorCode;

  /// The details of a failed service protocol extension RPC.
  final String? errorDetail;

  /// Creates a successful response to a service protocol extension RPC.
  ///
  /// Requires [result] to be a JSON object encoded as a string. When forming
  /// the JSON-RPC message [result] will be inlined directly.
  ServiceExtensionResponse.result(String result)
    : result = result,
      errorCode = null,
      errorDetail = null {
    // TODO: When NNBD is complete, delete the following line.
    checkNotNullable(result, "result");
  }

  /// Creates an error response to a service protocol extension RPC.
  ///
  /// Requires [errorCode] to be [invalidParams] or between [extensionErrorMin]
  /// and [extensionErrorMax]. Requires [errorDetail] to be a JSON object
  /// encoded as a string. When forming the JSON-RPC message [errorDetail] will
  /// be inlined directly.
  ServiceExtensionResponse.error(int errorCode, String errorDetail)
    : result = null,
      errorCode = errorCode,
      errorDetail = errorDetail {
    _validateErrorCode(errorCode);
    // TODO: When NNBD is complete, delete the following line.
    checkNotNullable(errorDetail, "errorDetail");
  }

  /// Invalid method parameter(s) error code.
  static const invalidParams = -32602;

  /// Generic extension error code.
  static const extensionError = -32000;

  /// Maximum extension provided error code.
  static const extensionErrorMax = -32000;

  /// Minimum extension provided error code.
  static const extensionErrorMin = -32016;

  static String _errorCodeMessage(int errorCode) {
    _validateErrorCode(errorCode);
    if (errorCode == invalidParams) {
      return "Invalid params";
    }
    return "Server error";
  }

  static _validateErrorCode(int errorCode) {
    // TODO: When NNBD is complete, delete the following line.
    checkNotNullable(errorCode, "errorCode");
    if (errorCode == invalidParams) return;
    if ((errorCode >= extensionErrorMin) && (errorCode <= extensionErrorMax)) {
      return;
    }
    throw new ArgumentError.value(errorCode, "errorCode", "Out of range");
  }

  /// Determines if this response represents an error.
  bool isError() => (errorCode != null) && (errorDetail != null);

  // ignore: unused_element, called from runtime/lib/developer.dart
  String _toString() {
    return result ??
        json.encode({
          'code': errorCode!,
          'message': _errorCodeMessage(errorCode!),
          'data': {'details': errorDetail!},
        });
  }
}

/// A service protocol extension handler. Registered with [registerExtension].
///
/// Must complete to a [ServiceExtensionResponse]. [method] is the method name
/// of the service protocol request, and [parameters] is a map holding the
/// parameters to the service protocol request.
///
/// *NOTE*: all parameter names and values are encoded as strings.
typedef Future<ServiceExtensionResponse> ServiceExtensionHandler(
  String method,
  Map<String, String> parameters,
);

/// Register a [ServiceExtensionHandler] that will be invoked in this isolate
/// for [method]. *NOTE*: Service protocol extensions must be registered
/// in each isolate.
///
/// *NOTE*: [method] must begin with 'ext.' and you should use the following
/// structure to avoid conflicts with other packages: 'ext.package.command'.
/// That is, immediately following the 'ext.' prefix, should be the registering
/// package name followed by another period ('.') and then the command name.
/// For example: 'ext.dart.io.getOpenFiles'.
///
/// Because service extensions are isolate specific, clients using extensions
/// must always include an 'isolateId' parameter with each RPC.
void registerExtension(String method, ServiceExtensionHandler handler) {
  // TODO: When NNBD is complete, delete the following line.
  checkNotNullable(method, 'method');
  if (!method.startsWith('ext.')) {
    throw new ArgumentError.value(method, 'method', 'Must begin with ext.');
  }
  if (_lookupExtension(method) != null) {
    throw new ArgumentError('Extension already registered: $method');
  }
  // TODO: When NNBD is complete, delete the following line.
  checkNotNullable(handler, 'handler');
  final zoneHandler = Zone.current.bindBinaryCallback(handler);
  _registerExtension(method, zoneHandler);
}

/// Whether the "Extension" stream currently has at least one listener.
///
/// A client of the VM service can register as a listener
/// on the extension stream using `listenStream` method.
/// The extension stream has a listener while at least one such
/// client has registered as a listener, and has not yet disconnected
/// again.
///
/// Calling [postEvent] while the stream has listeners will attempt to
/// deliver that event to all current listeners,
/// although a listener can disconnect before the event is delivered.
/// Calling [postEvent] when the stream has no listener means that
/// no-one will receive the event, and the call is effectively a no-op.
@pragma("vm:recognized", "other")
@pragma("vm:prefer-inline")
@pragma("vm:idempotent")
@Since('2.18')
external bool get extensionStreamHasListener;

/// Post an event of [eventKind] with payload of [eventData] to the "Extension"
/// event stream.
///
/// If [extensionStreamHasListener] is false, this method is a no-op.
/// Override [stream] to set the destination stream that the event should be
/// posted to. The [stream] may not start with an underscore or be a core VM
/// Service stream.
void postEvent(
  String eventKind,
  Map eventData, {
  @Since('3.0 ') String stream = 'Extension',
}) {
  const destinationStreamKey = '__destinationStream';
  // Keep protected streams in sync with `streams_` in runtime/vm/service.cc
  // `Extension` is the only stream that should not be protected here.
  final protectedStreams = <String>[
    'VM',
    'Isolate',
    'Debug',
    'GC',
    '_Echo',
    'HeapSnapshot',
    'Logging',
    'Timeline',
    'Profiler',
  ];

  if (protectedStreams.contains(stream)) {
    throw ArgumentError.value(
      stream,
      'stream',
      'Cannot be a protected stream.',
    );
  } else if (stream.startsWith('_')) {
    throw ArgumentError.value(
      stream,
      'stream',
      'Cannot start with an underscore.',
    );
  }

  if (!extensionStreamHasListener) {
    return;
  }
  // TODO: When NNBD is complete, delete the following two lines.
  checkNotNullable(eventKind, 'eventKind');
  checkNotNullable(eventData, 'eventData');
  checkNotNullable(stream, 'stream');
  Map mutableEventData = Map.from(eventData); // Shallow copy.
  mutableEventData[destinationStreamKey] = stream;
  String eventDataAsString = json.encode(mutableEventData);
  _postEvent(eventKind, eventDataAsString);
}

external void _postEvent(String eventKind, String eventData);

// Both of these functions are written inside C++ to avoid updating the data
// structures in Dart, getting an OOB, and observing stale state. Do not move
// these into Dart code unless you can ensure that the operations will can be
// done atomically. Native code lives in vm/isolate.cc-
// LookupServiceExtensionHandler and RegisterServiceExtensionHandler.
external ServiceExtensionHandler? _lookupExtension(String method);
external _registerExtension(String method, ServiceExtensionHandler handler);
