// Copyright (c) 2014, 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.

import 'dart:async';

import 'package:stack_trace/stack_trace.dart';
import 'package:stream_channel/stream_channel.dart';

import 'channel_manager.dart';
import 'exception.dart';
import 'utils.dart';

/// A JSON-RPC 2.0 client.
///
/// A client calls methods on a server and handles the server's responses to
/// those method calls. Methods can be called with [sendRequest], or with
/// [sendNotification] if no response is expected.
class Client {
  final ChannelManager _manager;

  /// The next request id.
  var _id = 0;

  /// The current batch of requests to be sent together.
  ///
  /// Each element is a JSON-serializable object.
  List _batch;

  /// The map of request ids to pending requests.
  final _pendingRequests = new Map<int, _Request>();

  /// Returns a [Future] that completes when the underlying connection is
  /// closed.
  ///
  /// This is the same future that's returned by [listen] and [close]. It may
  /// complete before [close] is called if the remote endpoint closes the
  /// connection.
  Future get done => _manager.done;

  /// Whether the underlying connection is closed.
  ///
  /// Note that this will be `true` before [close] is called if the remote
  /// endpoint closes the connection.
  bool get isClosed => _manager.isClosed;

  /// Creates a [Client] that communicates over [channel].
  ///
  /// Note that the client won't begin listening to [responses] until
  /// [Client.listen] is called.
  Client(StreamChannel<String> channel)
      : this.withoutJson(
            jsonDocument.bind(channel).transformStream(ignoreFormatExceptions));

  /// Creates a [Client] that communicates using decoded messages over
  /// [channel].
  ///
  /// Unlike [new Client], this doesn't read or write JSON strings. Instead, it
  /// reads and writes decoded maps or lists.
  ///
  /// Note that the client won't begin listening to [responses] until
  /// [Client.listen] is called.
  Client.withoutJson(StreamChannel channel)
      : _manager = new ChannelManager("Client", channel) {
    _manager.done.whenComplete(() {
      for (var request in _pendingRequests.values) {
        request.completer.completeError(
            new StateError("The client closed with pending requests."),
            StackTrace.current);
      }
      _pendingRequests.clear();
    }).catchError((_) {
      // Avoid an unhandled error.
    });
  }

  /// Starts listening to the underlying stream.
  ///
  /// Returns a [Future] that will complete when the connection is closed or
  /// when it has an error. This is the same as [done].
  ///
  /// [listen] may only be called once.
  Future listen() => _manager.listen(_handleResponse);

  /// Closes the underlying connection.
  ///
  /// Returns a [Future] that completes when all resources have been released.
  /// This is the same as [done].
  Future close() => _manager.close();

  /// Sends a JSON-RPC 2 request to invoke the given [method].
  ///
  /// If passed, [parameters] is the parameters for the method. This must be
  /// either an [Iterable] (to pass parameters by position) or a [Map] with
  /// [String] keys (to pass parameters by name). Either way, it must be
  /// JSON-serializable.
  ///
  /// If the request succeeds, this returns the response result as a decoded
  /// JSON-serializable object. If it fails, it throws an [RpcException]
  /// describing the failure.
  ///
  /// Throws a [StateError] if the client is closed while the request is in
  /// flight, or if the client is closed when this method is called.
  Future sendRequest(String method, [parameters]) {
    var id = _id++;
    _send(method, parameters, id);

    var completer = new Completer.sync();
    _pendingRequests[id] = new _Request(completer, new Chain.current());
    return completer.future;
  }

  /// Sends a JSON-RPC 2 request to invoke the given [method] without expecting
  /// a response.
  ///
  /// If passed, [parameters] is the parameters for the method. This must be
  /// either an [Iterable] (to pass parameters by position) or a [Map] with
  /// [String] keys (to pass parameters by name). Either way, it must be
  /// JSON-serializable.
  ///
  /// Since this is just a notification to which the server isn't expected to
  /// send a response, it has no return value.
  ///
  /// Throws a [StateError] if the client is closed when this method is called.
  void sendNotification(String method, [parameters]) =>
      _send(method, parameters);

  /// A helper method for [sendRequest] and [sendNotification].
  ///
  /// Sends a request to invoke [method] with [parameters]. If [id] is given,
  /// the request uses that id.
  void _send(String method, parameters, [int id]) {
    if (parameters is Iterable) parameters = parameters.toList();
    if (parameters is! Map && parameters is! List && parameters != null) {
      throw new ArgumentError('Only maps and lists may be used as JSON-RPC '
          'parameters, was "$parameters".');
    }
    if (isClosed) throw new StateError("The client is closed.");

    var message = <String, dynamic>{
      "jsonrpc": "2.0",
      "method": method
    };
    if (id != null) message["id"] = id;
    if (parameters != null) message["params"] = parameters;

    if (_batch != null) {
      _batch.add(message);
    } else {
      _manager.add(message);
    }
  }

  /// Runs [callback] and batches any requests sent until it returns.
  ///
  /// A batch of requests is sent in a single message on the underlying stream,
  /// and the responses are likewise sent back in a single message.
  ///
  /// [callback] may be synchronous or asynchronous. If it returns a [Future],
  /// requests will be batched until that Future returns; otherwise, requests
  /// will only be batched while synchronously executing [callback].
  ///
  /// If this is called in the context of another [withBatch] call, it just
  /// invokes [callback] without creating another batch. This means that
  /// responses are batched until the first batch ends.
  withBatch(callback()) {
    if (_batch != null) return callback();

    _batch = [];
    return tryFinally(callback, () {
      _manager.add(_batch);
      _batch = null;
    });
  }

  /// Handles a decoded response from the server.
  void _handleResponse(response) {
    if (response is List) {
      response.forEach(_handleSingleResponse);
    } else {
      _handleSingleResponse(response);
    }
  }

  /// Handles a decoded response from the server after batches have been
  /// resolved.
  void _handleSingleResponse(response) {
    if (!_isResponseValid(response)) return;
    var request = _pendingRequests.remove(response["id"]);
    if (response.containsKey("result")) {
      request.completer.complete(response["result"]);
    } else {
      request.completer.completeError(new RpcException(
            response["error"]["code"],
            response["error"]["message"],
            data: response["error"]["data"]),
          request.chain);
    }
  }

  /// Determines whether the server's response is valid per the spec.
  bool _isResponseValid(response) {
    if (response is! Map) return false;
    if (response["jsonrpc"] != "2.0") return false;
    if (!_pendingRequests.containsKey(response["id"])) return false;
    if (response.containsKey("result")) return true;

    if (!response.containsKey("error")) return false;
    var error = response["error"];
    if (error is! Map) return false;
    if (error["code"] is! int) return false;
    if (error["message"] is! String) return false;
    return true;
  }
}

/// A pending request to the server.
class _Request {
  /// The completer to use to complete the response future.
  final Completer completer;

  /// The stack chain from where the request was made.
  final Chain chain;

  _Request(this.completer, this.chain);
}
