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

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

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

/**
 * Instances of the class [WebSocketClientChannel] implement a
 * [ClientCommunicationChannel] that uses a [WebSocket] to communicate with
 * servers.
 */
class WebSocketClientChannel implements ClientCommunicationChannel {
  /**
   * The socket being wrapped.
   */
  final WebSocket socket;

  @override
  Stream<Response> responseStream;

  @override
  Stream<Notification> notificationStream;

  /**
   * Initialize a new [WebSocket] wrapper for the given [socket].
   */
  WebSocketClientChannel(this.socket) {
    Stream jsonStream = socket
        .where((data) => data is String)
        .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 socket.close();
  }

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

/**
 * Instances of the class [WebSocketServerChannel] implement a
 * [ServerCommunicationChannel] that uses a [WebSocket] to communicate with
 * clients.
 */
class WebSocketServerChannel implements ServerCommunicationChannel {
  /**
   * The socket being wrapped.
   */
  final WebSocket socket;

  /**
   * The instrumentation service that is to be used by this analysis server.
   */
  final InstrumentationService instrumentationService;

  /**
   * Initialize a newly create [WebSocket] wrapper to wrap the given [socket].
   */
  WebSocketServerChannel(this.socket, this.instrumentationService);

  @override
  void close() {
    socket.close(WebSocketStatus.NORMAL_CLOSURE);
  }

  @override
  void listen(void onRequest(Request request),
      {void onError(), void onDone()}) {
    socket.listen((data) => readRequest(data, onRequest),
        onError: onError, onDone: onDone);
  }

  /**
   * Read a request from the given [data] and use the given function to handle
   * the request.
   */
  void readRequest(Object data, void onRequest(Request request)) {
    if (data is String) {
      instrumentationService.logRequest(data);
      // Parse the string as a JSON descriptor and process the resulting
      // structure as a request.
      ServerPerformanceStatistics.serverChannel.makeCurrentWhile(() {
        Request request = new Request.fromString(data);
        if (request == null) {
          sendResponse(new Response.invalidRequestFormat());
          return;
        }
        onRequest(request);
      });
    } else if (data is List<int>) {
      // TODO(brianwilkerson) Implement a more efficient protocol.
      sendResponse(new Response.invalidRequestFormat());
    } else {
      sendResponse(new Response.invalidRequestFormat());
    }
  }

  @override
  void sendNotification(Notification notification) {
    ServerPerformanceStatistics.serverChannel.makeCurrentWhile(() {
      String jsonEncoding = JSON.encode(notification.toJson());
      socket.add(jsonEncoding);
      instrumentationService.logNotification(jsonEncoding);
    });
  }

  @override
  void sendResponse(Response response) {
    ServerPerformanceStatistics.serverChannel.makeCurrentWhile(() {
      String jsonEncoding = JSON.encode(response.toJson());
      socket.add(jsonEncoding);
      instrumentationService.logResponse(jsonEncoding);
    });
  }
}
