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

// @dart = 2.5

part of dart._vmservice;

enum MessageType { Request, Notification, Response }

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

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

  // Is a notification message (no serial)
  final MessageType type;

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

  final String method;

  final Map params = new Map();
  final Map result = new Map();
  final Map error = new Map();

  factory Message.fromJsonRpc(Client client, Map map) {
    if (map.containsKey('id')) {
      final id = map['id'];
      if (id != null && id is! num && id is! String) {
        throw new Exception('"id" must be a number, string, or null.');
      }
      if (map.containsKey('method')) {
        return new Message._fromJsonRpcRequest(client, map);
      }
      if (map.containsKey('result')) {
        return new Message._fromJsonRpcResult(client, map);
      }
      if (map.containsKey('error')) {
        return new Message._fromJsonRpcError(client, map);
      }
    } else if (map.containsKey('method')) {
      return new Message._fromJsonRpcNotification(client, map);
    }
    throw new Exception('Invalid message format');
  }

  // http://www.jsonrpc.org/specification#request_object
  Message._fromJsonRpcRequest(Client client, Map map)
      : client = client,
        type = MessageType.Request,
        serial = map['id'],
        method = map['method'] {
    if (map['params'] != null) {
      params.addAll(map['params']);
    }
  }

  // http://www.jsonrpc.org/specification#notification
  Message._fromJsonRpcNotification(Client client, Map map)
      : client = client,
        type = MessageType.Notification,
        method = map['method'],
        serial = null {
    if (map['params'] != null) {
      params.addAll(map['params']);
    }
  }

  // http://www.jsonrpc.org/specification#response_object
  Message._fromJsonRpcResult(Client client, Map map)
      : client = client,
        type = MessageType.Response,
        serial = map['id'],
        method = null {
    result.addAll(map['result']);
  }

  // http://www.jsonrpc.org/specification#response_object
  Message._fromJsonRpcError(Client client, Map map)
      : client = client,
        type = MessageType.Response,
        serial = map['id'],
        method = null {
    error.addAll(map['error']);
  }

  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,
        type = MessageType.Request,
        serial = '';

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

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

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

  dynamic toJson() {
    throw 'unsupported';
  }

  dynamic forwardToJson([Map overloads]) {
    Map<dynamic, dynamic> json = {'jsonrpc': '2.0', 'id': serial};
    switch (type) {
      case MessageType.Request:
      case MessageType.Notification:
        json['method'] = method;
        if (params.isNotEmpty) {
          json['params'] = params;
        }
        break;
      case MessageType.Response:
        if (result.isNotEmpty) {
          json['result'] = result;
        }
        if (error.isNotEmpty) {
          json['error'] = error;
        }
    }
    if (overloads != null) {
      json.addAll(overloads);
    }
    return json;
  }

  // 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<String> _makeAllString(List list) {
    if (list == null) {
      return null;
    }
    var new_list = new List<String>(list.length);
    for (var i = 0; i < list.length; i++) {
      new_list[i] = list[i].toString();
    }
    return new_list;
  }

  Future<Response> sendToIsolate(SendPort sendPort) {
    final receivePort = new RawReceivePort();
    receivePort.handler = (value) {
      receivePort.close();
      _setResponseFromPort(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(new Response.internalError(
          '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<Response> sendToVM() {
    final receivePort = new RawReceivePort();
    receivePort.handler = (value) {
      receivePort.close();
      _setResponseFromPort(value);
    };
    var keys = params.keys.toList(growable: false);
    var values = params.values.toList(growable: false);
    if (!_methodNeedsObjectParameters(method)) {
      keys = _makeAllString(keys);
      values = _makeAllString(values);
    }

    final request = new List(6)
      ..[0] = 0 // Make room for OOB message type.
      ..[1] = receivePort.sendPort
      ..[2] = serial
      ..[3] = method
      ..[4] = keys
      ..[5] = values;

    if (_methodNeedsObjectParameters(method)) {
      // We use a different method invocation path here.
      sendObjectRootServiceMessage(request);
    } else {
      sendRootServiceMessage(request);
    }

    return _completer.future;
  }

  void _setResponseFromPort(dynamic response) {
    if (response == null) {
      // We should only have a null response for Notifications.
      assert(type == MessageType.Notification);
      return null;
    }
    _completer.complete(Response.from(response));
  }

  void setResponse(String response) {
    _completer.complete(new Response(ResponsePayloadKind.String, response));
  }

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

bool sendIsolateServiceMessage(SendPort sp, List m)
    native "VMService_SendIsolateServiceMessage";

void sendRootServiceMessage(List m) native "VMService_SendRootServiceMessage";

void sendObjectRootServiceMessage(List m)
    native "VMService_SendObjectRootServiceMessage";
