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

library channel.byte_stream;

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:analysis_server/src/channel/channel.dart';
import 'package:analysis_server/src/protocol.dart';

/**
 * Instances of the class [ByteStreamClientChannel] implement a
 * [ClientCommunicationChannel] that uses a stream and a sink (typically,
 * standard input and standard output) to communicate with servers.
 */
class ByteStreamClientChannel implements ClientCommunicationChannel {
  final Stream input;
  final IOSink output;

  @override
  Stream<Response> responseStream;

  @override
  Stream<Notification> notificationStream;

  ByteStreamClientChannel(this.input, this.output) {
    Stream jsonStream = input.transform((new Utf8Codec()).decoder)
        .transform(new LineSplitter())
        .transform(new JsonStreamDecoder())
        .where((json) => json is Map)
        .asBroadcastStream();
    responseStream = jsonStream
        .where((json) => json[Notification.EVENT] == null)
        .transform(new ResponseConverter())
        .asBroadcastStream();
    notificationStream = jsonStream
        .where((json) => json[Notification.EVENT] != null)
        .transform(new NotificationConverter())
        .asBroadcastStream();
  }

  @override
  Future close() {
    return output.close();
  }

  @override
  Future<Response> sendRequest(Request request) {
    String id = request.id;
    output.writeln(JSON.encode(request.toJson()));
    return responseStream.firstWhere((Response response) => response.id == id);
  }
}

/**
 * Instances of the class [ByteStreamServerChannel] implement a
 * [ServerCommunicationChannel] that uses a stream and a sink (typically,
 * standard input and standard output) to communicate with clients.
 */
class ByteStreamServerChannel implements ServerCommunicationChannel {
  final Stream input;
  final IOSink output;

  /**
   * Completer that will be signalled when the input stream is closed.
   */
  final Completer _closed = new Completer();

  ByteStreamServerChannel(this.input, this.output);

  /**
   * Future that will be completed when the input stream is closed.
   */
  Future get closed {
    return _closed.future;
  }

  @override
  void close() {
    output.flush().then((_) {
      if (!_closed.isCompleted) {
        _closed.complete();
      }
    });
  }

  @override
  void listen(void onRequest(Request request), {Function onError, void
      onDone()}) {
    input.transform((new Utf8Codec()).decoder).transform(new LineSplitter()
        ).listen((String data) => _readRequest(data, onRequest), onError: onError,
        onDone: () {
      close();
      onDone();
    });
  }

  @override
  void sendNotification(Notification notification) {
    // Don't send any further notifications after the communication channel is
    // closed.
    if (_closed.isCompleted) {
      return;
    }
    ServerCommunicationChannel.ToJson.start();
    String jsonEncoding = JSON.encode(notification.toJson());
    ServerCommunicationChannel.ToJson.stop();
    output.writeln(jsonEncoding);
  }

  @override
  void sendResponse(Response response) {
    // Don't send any further responses after the communication channel is
    // closed.
    if (_closed.isCompleted) {
      return;
    }
    ServerCommunicationChannel.ToJson.start();
    String jsonEncoding = JSON.encode(response.toJson());
    ServerCommunicationChannel.ToJson.stop();
    output.writeln(jsonEncoding);
  }

  /**
   * Read a request from the given [data] and use the given function to handle
   * the request.
   */
  void _readRequest(Object data, void onRequest(Request request)) {
    // Ignore any further requests after the communication channel is closed.
    if (_closed.isCompleted) {
      return;
    }
    // Parse the string as a JSON descriptor and process the resulting
    // structure as a request.
    ServerCommunicationChannel.FromJson.start();
    Request request = new Request.fromString(data);
    ServerCommunicationChannel.FromJson.stop();
    if (request == null) {
      sendResponse(new Response.invalidRequestFormat());
      return;
    }
    onRequest(request);
  }
}
