// Copyright (c) 2016, 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;

/// Service protocol is the protocol that a client like the Observatory
/// could use to access the services provided by the Dart VM for
/// debugging and inspecting Dart programs. This class encapsulates the
/// version number and Uri for accessing this service.
class ServiceProtocolInfo {
  /// The major version of the protocol. If the running Dart environment does
  /// not support the service protocol, this is 0.
  final int majorVersion = _getServiceMajorVersion();

  /// The minor version of the protocol. If the running Dart environment does
  /// not support the service protocol, this is 0.
  final int minorVersion = _getServiceMinorVersion();

  /// The Uri to connect to the debugger client hosted by the service. If the
  /// web server is not running, this will be null.
  final Uri? serverUri;

  /// The Uri to connect to the service via web socket. If the web server is
  /// not running, this will be null.
  Uri? get serverWebSocketUri {
    Uri? uri = serverUri;
    if (uri != null) {
      final pathSegments = <String>[];
      if (uri.pathSegments.isNotEmpty) {
        pathSegments.addAll(uri.pathSegments.where(
          // Strip out the empty string that appears at the end of path segments.
          // Empty string elements will result in an extra '/' being added to the
          // URI.
          (s) => s.isNotEmpty,
        ));
      }
      pathSegments.add('ws');
      uri = uri.replace(scheme: 'ws', pathSegments: pathSegments);
    }
    return uri;
  }

  ServiceProtocolInfo(this.serverUri);

  String toString() {
    if (serverUri != null) {
      return 'Dart VM Service Protocol v$majorVersion.$minorVersion '
          'listening on $serverUri';
    } else {
      return 'Dart VM Service Protocol v$majorVersion.$minorVersion';
    }
  }
}

/// Access information about the service protocol and control the web server
/// that provides access to the services provided by the Dart VM for
/// debugging and inspecting Dart programs.
class Service {
  /// Get information about the service protocol (version number and
  /// Uri to access the service).
  static Future<ServiceProtocolInfo> getInfo() async {
    // Port to receive response from service isolate.
    final RawReceivePort receivePort =
        new RawReceivePort(null, 'Service.getInfo');
    final Completer<Uri?> uriCompleter = new Completer<Uri?>();
    receivePort.handler = (Uri? uri) => uriCompleter.complete(uri);
    // Request the information from the service isolate.
    _getServerInfo(receivePort.sendPort);
    // Await the response from the service isolate.
    Uri? uri = await uriCompleter.future;
    // Close the port.
    receivePort.close();
    return new ServiceProtocolInfo(uri);
  }

  /// Control the web server that the service protocol is accessed through.
  /// [enable] is used as a toggle to enable or disable the web server
  /// servicing requests. If [silenceOutput] is provided and is true,
  /// the server will not output information to the console.
  static Future<ServiceProtocolInfo> controlWebServer(
      {bool enable = false, bool? silenceOutput}) async {
    // TODO: When NNBD is complete, delete the following line.
    ArgumentError.checkNotNull(enable, 'enable');
    // Port to receive response from service isolate.
    final RawReceivePort receivePort =
        new RawReceivePort(null, 'Service.controlWebServer');
    final Completer<Uri> uriCompleter = new Completer<Uri>();
    receivePort.handler = (Uri uri) => uriCompleter.complete(uri);
    // Request the information from the service isolate.
    _webServerControl(receivePort.sendPort, enable, silenceOutput);
    // Await the response from the service isolate.
    Uri uri = await uriCompleter.future;
    // Close the port.
    receivePort.close();
    return new ServiceProtocolInfo(uri);
  }

  /// Returns a [String] token representing the ID of [isolate].
  ///
  /// Returns null if the running Dart environment does not support the service
  /// protocol.
  static String? getIsolateID(Isolate isolate) {
    // TODO: When NNBD is complete, delete the following line.
    ArgumentError.checkNotNull(isolate, 'isolate');
    return _getIsolateIDFromSendPort(isolate.controlPort);
  }
}

/// [sendPort] will receive a Uri or null.
external void _getServerInfo(SendPort sendPort);

/// [sendPort] will receive a Uri or null.
external void _webServerControl(
    SendPort sendPort, bool enable, bool? silenceOutput);

/// Returns the major version of the service protocol.
external int _getServiceMajorVersion();

/// Returns the minor version of the service protocol.
external int _getServiceMinorVersion();

/// Returns the service id for the isolate that owns [sendPort].
external String? _getIsolateIDFromSendPort(SendPort sendPort);
