// Copyright (c) 2013, 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._vmservice;

class Message {
  final Completer _completer = new Completer.sync();
  bool get completed => _completer.isCompleted;

  /// Future of response.
  Future<String> get response => _completer.future;
  Client client;

  // Client-side identifier for this message.
  final serial;

  // In new messages.
  final String method;

  // In old messages.
  final List path = new List();

  final Map params = new Map();

  void _setPath(List<String> pathSegments) {
    if (pathSegments == null) {
      return;
    }
    pathSegments.forEach((String segment) {
      if (segment == null || segment == '') {
        return;
      }
      path.add(segment);
    });
  }

  Message.fromJsonRpc(this.client, Map map)
      : serial = map['id'],
        method = map['method'] {
    if (map['params'] != null) {
      params.addAll(map['params']);
    }
  }

  static String _methodNameFromUri(Uri uri) {
    if (uri == null) {
      return '';
    }
    if (uri.pathSegments.length == 0) {
      return '';
    }
    return uri.pathSegments[0];
  }

  Message.forMethod(String method)
      : client = null,
        method = method,
        serial = '';

  Message.fromUri(this.client, Uri uri)
      : serial = '',
        method = _methodNameFromUri(uri) {
    params.addAll(uri.queryParameters);
  }

  Message.forIsolate(this.client, Uri uri, RunningIsolate isolate)
      : serial = '',
        method = _methodNameFromUri(uri) {
    params.addAll(uri.queryParameters);
    params['isolateId'] = isolate.serviceId;
  }

  Uri toUri() {
    return new Uri(path: method, queryParameters: params);
  }

  dynamic toJson() {
    return {'path': path, 'params': params};
  }

  // Calls toString on all non-String elements of [list]. We do this so all
  // elements in the list are strings, making consumption by C++ simpler.
  // This has a side effect that boolean literal values like true become 'true'
  // and thus indistinguishable from the string literal 'true'.
  List _makeAllString(List list) {
    if (list == null) {
      return null;
    }
    for (var i = 0; i < list.length; i++) {
      if (list[i] is String) {
        continue;
      }
      list[i] = list[i].toString();
    }
    return list;
  }

  Future<String> send(SendPort sendPort) {
    final receivePort = new RawReceivePort();
    receivePort.handler = (value) {
      receivePort.close();
      _completer.complete(value);
    };
    var keys = _makeAllString(params.keys.toList(growable: false));
    var values = _makeAllString(params.values.toList(growable: false));
    var request = new List(6)
      ..[0] = 0 // Make room for OOB message type.
      ..[1] = receivePort.sendPort
      ..[2] = serial
      ..[3] = method
      ..[4] = keys
      ..[5] = values;
    if (!sendIsolateServiceMessage(sendPort, request)) {
      receivePort.close();
      _completer.complete(JSON.encode({
        'type': 'ServiceError',
        'id': '',
        'kind': 'InternalError',
        'message': 'could not send message [${serial}] to isolate',
      }));
    }
    return _completer.future;
  }

  // We currently support two ways of passing parameters from Dart code to C
  // code. The original way always converts the parameters to strings before
  // passing them over. Our goal is to convert all C handlers to take the
  // parameters as Dart objects but until the conversion is complete, we
  // maintain the list of supported methods below.
  bool _methodNeedsObjectParameters(String method) {
    switch (method) {
      case '_listDevFS':
      case '_listDevFSFiles':
      case '_createDevFS':
      case '_deleteDevFS':
      case '_writeDevFSFile':
      case '_writeDevFSFiles':
      case '_readDevFSFile':
      case '_spawnUri':
        return true;
      default:
        return false;
    }
  }

  Future<String> sendToVM() {
    final receivePort = new RawReceivePort();
    receivePort.handler = (value) {
      receivePort.close();
      _completer.complete(value);
    };
    if (_methodNeedsObjectParameters(method)) {
      // We use a different method invocation path here.
      var keys = params.keys.toList(growable: false);
      var values = params.values.toList(growable: false);
      var request = new List(6)
        ..[0] = 0 // Make room for OOB message type.
        ..[1] = receivePort.sendPort
        ..[2] = serial
        ..[3] = method
        ..[4] = keys
        ..[5] = values;
      sendObjectRootServiceMessage(request);
      return _completer.future;
    } else {
      var keys = _makeAllString(params.keys.toList(growable: false));
      var values = _makeAllString(params.values.toList(growable: false));
      var request = new List(6)
        ..[0] = 0 // Make room for OOB message type.
        ..[1] = receivePort.sendPort
        ..[2] = serial
        ..[3] = method
        ..[4] = keys
        ..[5] = values;
      sendRootServiceMessage(request);
      return _completer.future;
    }
  }

  void setResponse(String response) {
    _completer.complete(response);
  }

  void setErrorResponse(int code, String details) {
    _completer
        .complete(encodeRpcError(this, code, details: '$method: $details'));
  }
}

external bool sendIsolateServiceMessage(SendPort sp, List m);
external void sendRootServiceMessage(List m);
external void sendObjectRootServiceMessage(List m);
