// 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.
final 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.
  @Since('2.14')
  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.
final 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<String?> completer = new Completer<String?>();
    receivePort.handler = (String? uriString) => completer.complete(uriString);
    // Request the information from the service isolate.
    _getServerInfo(receivePort.sendPort);
    // Await the response from the service isolate.
    String? uriString = await completer.future;
    Uri? uri = uriString == null ? null : Uri.parse(uriString);
    // 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 {
    // Port to receive response from service isolate.
    final RawReceivePort receivePort = new RawReceivePort(
      null,
      'Service.controlWebServer',
    );
    final Completer<String?> completer = new Completer<String?>();
    receivePort.handler = (String? uriString) => completer.complete(uriString);
    // Request the information from the service isolate.
    _webServerControl(receivePort.sendPort, enable, silenceOutput);
    // Await the response from the service isolate.
    String? uriString = await completer.future;
    Uri? uri = uriString == null ? null : Uri.parse(uriString);
    // 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.
  ///
  /// To get the isolate id of the current isolate, pass [Isolate.current] as
  /// the [isolate] parameter.
  @Since('3.2')
  static String? getIsolateId(Isolate isolate) {
    return _getIsolateIdFromSendPort(isolate.controlPort);
  }

  /// Returns a [String] token representing the ID of [isolate].
  ///
  /// Returns null if the running Dart environment does not support the service
  /// protocol.
  @Deprecated("Use getIsolateId instead")
  static String? getIsolateID(Isolate isolate) {
    return _getIsolateIdFromSendPort(isolate.controlPort);
  }

  /// Returns a [String] token representing the ID of [object].
  ///
  /// Returns null if the running Dart environment does not support the service
  /// protocol.
  @Since('3.2')
  static String? getObjectId(Object object) {
    return _getObjectId(object);
  }
}

/// [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);

/// Returns the service id of [object].
external String? _getObjectId(Object object);
