// 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.

/// Note: the VM concatenates all patch files into a single patch file. This
/// file is the first patch in "dart:developer" which contains all the imports
/// used by patches of that library. We plan to change this when we have a
/// shared front end and simply use parts.

import "dart:_internal" show patch;

import "dart:async" show Future, Zone;

import "dart:isolate" show SendPort;

/// These are the additional parts of this patch library:
// part "profiler.dart"
// part "timeline.dart"

@patch
bool debugger({bool when: true, String message}) native "Developer_debugger";

@patch
Object inspect(Object object) native "Developer_inspect";

@patch
void log(String message,
    {DateTime time,
    int sequenceNumber,
    int level: 0,
    String name: '',
    Zone zone,
    Object error,
    StackTrace stackTrace}) {
  if (message is! String) {
    throw new ArgumentError.value(message, "message", "Must be a String");
  }
  time ??= new DateTime.now();
  if (time is! DateTime) {
    throw new ArgumentError.value(time, "time", "Must be a DateTime");
  }
  if (sequenceNumber == null) {
    sequenceNumber = _nextSequenceNumber++;
  } else {
    _nextSequenceNumber = sequenceNumber + 1;
  }
  _log(message, time.millisecondsSinceEpoch, sequenceNumber, level, name, zone,
      error, stackTrace);
}

int _nextSequenceNumber = 0;

_log(String message, int timestamp, int sequenceNumber, int level, String name,
    Zone zone, Object error, StackTrace stackTrace) native "Developer_log";

@patch
void _postEvent(String eventKind, String eventData)
    native "Developer_postEvent";

@patch
ServiceExtensionHandler _lookupExtension(String method)
    native "Developer_lookupExtension";

@patch
_registerExtension(String method, ServiceExtensionHandler handler)
    native "Developer_registerExtension";

// This code is only invoked when there is no other Dart code on the stack.
@pragma("vm:entry-point", !const bool.fromEnvironment("dart.vm.product"))
_runExtension(
    ServiceExtensionHandler handler,
    String method,
    List<String> parameterKeys,
    List<String> parameterValues,
    SendPort replyPort,
    Object id,
    bool trace_service) {
  var parameters = <String, String>{};
  for (var i = 0; i < parameterKeys.length; i++) {
    parameters[parameterKeys[i]] = parameterValues[i];
  }
  var response;
  try {
    response = handler(method, parameters);
  } catch (e, st) {
    var errorDetails = (st == null) ? '$e' : '$e\n$st';
    response = new ServiceExtensionResponse.error(
        ServiceExtensionResponse.kExtensionError, errorDetails);
    _postResponse(replyPort, id, response, trace_service);
    return;
  }
  if (response is! Future) {
    response = new ServiceExtensionResponse.error(
        ServiceExtensionResponse.kExtensionError,
        "Extension handler must return a Future");
    _postResponse(replyPort, id, response, trace_service);
    return;
  }
  response.catchError((e, st) {
    // Catch any errors eagerly and wrap them in a ServiceExtensionResponse.
    var errorDetails = (st == null) ? '$e' : '$e\n$st';
    return new ServiceExtensionResponse.error(
        ServiceExtensionResponse.kExtensionError, errorDetails);
  }).then((response) {
    // Post the valid response or the wrapped error after verifying that
    // the response is a ServiceExtensionResponse.
    if (response is! ServiceExtensionResponse) {
      response = new ServiceExtensionResponse.error(
          ServiceExtensionResponse.kExtensionError,
          "Extension handler must complete to a ServiceExtensionResponse");
    }
    _postResponse(replyPort, id, response, trace_service);
  }).catchError((e, st) {
    // We do not expect any errors to occur in the .then or .catchError blocks
    // but, suppress them just in case.
  });
}

// This code is only invoked by _runExtension.
_postResponse(SendPort replyPort, Object id, ServiceExtensionResponse response,
    bool trace_service) {
  assert(replyPort != null);
  if (id == null) {
    if (trace_service) {
      print("vm-service: posting no response for request");
    }
    // No id -> no response.
    replyPort.send(null);
    return;
  }
  assert(id != null);
  StringBuffer sb = new StringBuffer();
  sb.write('{"jsonrpc":"2.0",');
  if (response._isError()) {
    if (trace_service) {
      print("vm-service: posting error response for request $id");
    }
    sb.write('"error":');
  } else {
    if (trace_service) {
      print("vm-service: posting response for request $id");
    }
    sb.write('"result":');
  }
  sb.write('${response._toString()},');
  if (id is String) {
    sb.write('"id":"$id"}');
  } else {
    sb.write('"id":$id}');
  }
  replyPort.send(sb.toString());
}

@patch
int _getServiceMajorVersion() native "Developer_getServiceMajorVersion";

@patch
int _getServiceMinorVersion() native "Developer_getServiceMinorVersion";

@patch
void _getServerInfo(SendPort sendPort) native "Developer_getServerInfo";

@patch
void _webServerControl(SendPort sendPort, bool enable)
    native "Developer_webServerControl";

@patch
String _getIsolateIDFromSendPort(SendPort sendPort)
    native "Developer_getIsolateIDFromSendPort";
