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

/**
 * Support for interacting with an analysis server that is running in a separate
 * process.
 */
import 'dart:async';
import 'dart:collection';
import 'dart:convert' hide JsonDecoder;
import 'dart:io';
import 'dart:math' as math;

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:path/path.dart' as path;

import 'logger.dart';

/**
 * Return the current time expressed as milliseconds since the epoch.
 */
int get currentTime => new DateTime.now().millisecondsSinceEpoch;

/**
 * ???
 */
class ErrorMap {
  /**
   * A table mapping file paths to the errors associated with that file.
   */
  final Map<String, List<AnalysisError>> pathMap =
      new HashMap<String, List<AnalysisError>>();

  /**
   * Initialize a newly created error map.
   */
  ErrorMap();

  /**
   * Initialize a newly created error map to contain the same mapping as the
   * given [errorMap].
   */
  ErrorMap.from(ErrorMap errorMap) {
    pathMap.addAll(errorMap.pathMap);
  }

  void operator []=(String filePath, List<AnalysisError> errors) {
    pathMap[filePath] = errors;
  }
}

/**
 * Data that has been collected about a request sent to the server.
 */
class RequestData {
  /**
   * The unique id of the request.
   */
  final String id;

  /**
   * The method that was requested.
   */
  final String method;

  /**
   * The request parameters.
   */
  final Map<String, dynamic> params;

  /**
   * The time at which the request was sent.
   */
  final int requestTime;

  /**
   * The time at which the response was received, or `null` if no response has
   * been received.
   */
  int responseTime = null;

  /**
   * The response that was received.
   */
  Response _response;

  /**
   * The completer that will be completed when a response is received.
   */
  Completer<Response> _responseCompleter;

  /**
   * Initialize a newly created set of request data.
   */
  RequestData(this.id, this.method, this.params, this.requestTime);

  /**
   * Return the number of milliseconds that elapsed between the request and the
   * response. This getter assumes that the response was received.
   */
  int get elapsedTime => responseTime - requestTime;

  /**
   * Return a future that will complete when a response is received.
   */
  Future<Response> get respondedTo {
    if (_response != null) {
      return new Future.value(_response);
    }
    if (_responseCompleter == null) {
      _responseCompleter = new Completer<Response>();
    }
    return _responseCompleter.future;
  }

  /**
   * Record that the given [response] was received.
   */
  void recordResponse(Response response) {
    if (_response != null) {
      stdout.writeln(
          'Received a second response to a $method request (id = $id)');
      return;
    }
    responseTime = currentTime;
    _response = response;
    if (_responseCompleter != null) {
      _responseCompleter.complete(response);
      _responseCompleter = null;
    }
  }
}

/**
 * A utility for starting and communicating with an analysis server that is
 * running in a separate process.
 */
class Server {
  /**
   * The label used for communications from the client.
   */
  static const String fromClient = 'client';

  /**
   * The label used for normal communications from the server.
   */
  static const String fromServer = 'server';

  /**
   * The label used for output written by the server on [fromStderr].
   */
  static const String fromStderr = 'stderr';

  /**
   * The logger to which the communications log should be written, or `null` if
   * the log should not be written.
   */
  final Logger logger;

  /**
   * The process in which the server is running, or `null` if the server hasn't
   * been started yet.
   */
  Process _process = null;

  /**
   * Number that should be used to compute the 'id' to send in the next command
   * sent to the server.
   */
  int _nextId = 0;

  /**
   * The analysis roots that are included.
   */
  List<String> _analysisRootIncludes = <String>[];

  /**
   * A list containing the paths of files for which an overlay has been created.
   */
  List<String> filesWithOverlays = <String>[];

  /**
   * The files that the server reported as being analyzed.
   */
  List<String> _analyzedFiles = <String>[];

  /**
   * A mapping from the absolute paths of files to the most recent set of errors
   * received for that file.
   */
  ErrorMap _errorMap = new ErrorMap();

  /**
   * The completer that will be completed the next time a 'server.status'
   * notification is received from the server with 'analyzing' set to false.
   */
  Completer<void> _analysisFinishedCompleter;

  /**
   * The completer that will be completed the next time a 'server.connected'
   * notification is received from the server.
   */
  Completer<void> _serverConnectedCompleter;

  /**
   * A table mapping the ids of requests that have been sent to the server to
   * data about those requests.
   */
  final Map<String, RequestData> _requestDataMap = <String, RequestData>{};

  /**
   * A table mapping the number of times a request whose 'event' is equal to the
   * key was sent to the server.
   */
  final Map<String, int> _notificationCountMap = <String, int>{};

  /**
   * Initialize a new analysis server. The analysis server is not running and
   * must be started using [start].
   *
   * If a [logger] is provided, the communications between the client (this
   * test) and the server will be written to it.
   */
  Server({this.logger = null});

  /**
   * Return a future that will complete when a 'server.status' notification is
   * received from the server with 'analyzing' set to false.
   *
   * The future will only be completed by 'server.status' notifications that are
   * received after this function call, so it is safe to use this getter
   * multiple times in one test; each time it is used it will wait afresh for
   * analysis to finish.
   */
  Future get analysisFinished {
    if (_analysisFinishedCompleter == null) {
      _analysisFinishedCompleter = new Completer<void>();
    }
    return _analysisFinishedCompleter.future;
  }

  /**
   * Return a list of the paths of files that are currently being analyzed.
   */
  List<String> get analyzedDartFiles {
    bool isAnalyzed(String filePath) {
      // TODO(brianwilkerson) This should use the path package to determine
      // inclusion, and needs to take exclusions into account.
      for (String includedRoot in _analysisRootIncludes) {
        if (filePath.startsWith(includedRoot)) {
          return true;
        }
      }
      return false;
    }

    List<String> analyzedFiles = <String>[];
    for (String filePath in _analyzedFiles) {
      if (filePath.endsWith('.dart') && isAnalyzed(filePath)) {
        analyzedFiles.add(filePath);
      }
    }
    return analyzedFiles;
  }

  /**
   * Return a table mapping the absolute paths of files to the most recent set
   * of errors received for that file. The content of the map will not change
   * when new sets of errors are received.
   */
  ErrorMap get errorMap => new ErrorMap.from(_errorMap);

  /**
   * Compute a mapping from each of the file paths in the given list of
   * [filePaths] to the list of errors in the file at that path.
   */
  Future<ErrorMap> computeErrorMap(List<String> filePaths) async {
    ErrorMap errorMap = new ErrorMap();
    List<Future> futures = <Future>[];
    for (String filePath in filePaths) {
      RequestData requestData = sendAnalysisGetErrors(filePath);
      futures.add(requestData.respondedTo.then((Response response) {
        if (response.result != null) {
          AnalysisGetErrorsResult result =
              new AnalysisGetErrorsResult.fromResponse(response);
          errorMap[filePath] = result.errors;
        }
      }));
    }
    await Future.wait(futures);
    return errorMap;
  }

  /**
   * Print information about the communications with the server.
   */
  void printStatistics() {
    void writeSpaces(int count) {
      for (int i = 0; i < count; i++) {
        stdout.write(' ');
      }
    }

    //
    // Print information about the requests that were sent.
    //
    stdout.writeln('Request Counts');
    if (_requestDataMap.isEmpty) {
      stdout.writeln('  none');
    } else {
      Map<String, List<RequestData>> requestsByMethod =
          <String, List<RequestData>>{};
      _requestDataMap.values.forEach((RequestData requestData) {
        requestsByMethod
            .putIfAbsent(requestData.method, () => <RequestData>[])
            .add(requestData);
      });
      List<String> keys = requestsByMethod.keys.toList();
      keys.sort();
      int maxCount = requestsByMethod.values
          .fold(0, (int count, List<RequestData> list) => count + list.length);
      int countWidth = maxCount.toString().length;
      for (String key in keys) {
        List<RequestData> requests = requestsByMethod[key];
        int noResponseCount = 0;
        int responseCount = 0;
        int minTime = -1;
        int maxTime = -1;
        int totalTime = 0;
        requests.forEach((RequestData data) {
          if (data.responseTime == null) {
            noResponseCount++;
          } else {
            responseCount++;
            int time = data.elapsedTime;
            minTime = minTime < 0 ? time : math.min(minTime, time);
            maxTime = math.max(maxTime, time);
            totalTime += time;
          }
        });
        String count = requests.length.toString();
        writeSpaces(countWidth - count.length);
        stdout.write('  ');
        stdout.write(count);
        stdout.write(' - ');
        stdout.write(key);
        if (noResponseCount > 0) {
          stdout.write(', ');
          stdout.write(noResponseCount);
          stdout.write(' with no response');
        }
        if (maxTime >= 0) {
          stdout.write(' (');
          stdout.write(minTime);
          stdout.write(', ');
          stdout.write(totalTime / responseCount);
          stdout.write(', ');
          stdout.write(maxTime);
          stdout.write(')');
        }
        stdout.writeln();
      }
    }
    //
    // Print information about the notifications that were received.
    //
    stdout.writeln();
    stdout.writeln('Notification Counts');
    if (_notificationCountMap.isEmpty) {
      stdout.writeln('  none');
    } else {
      List<String> keys = _notificationCountMap.keys.toList();
      keys.sort();
      int maxCount = _notificationCountMap.values.fold(0, math.max);
      int countWidth = maxCount.toString().length;
      for (String key in keys) {
        String count = _notificationCountMap[key].toString();
        writeSpaces(countWidth - count.length);
        stdout.write('  ');
        stdout.write(count);
        stdout.write(' - ');
        stdout.writeln(key);
      }
    }
  }

  /**
   * Remove any existing overlays.
   */
  void removeAllOverlays() {
    Map<String, dynamic> files = new HashMap<String, dynamic>();
    for (String path in filesWithOverlays) {
      files[path] = new RemoveContentOverlay();
    }
    sendAnalysisUpdateContent(files);
  }

  RequestData sendAnalysisGetErrors(String file) {
    var params = new AnalysisGetErrorsParams(file).toJson();
    return _send("analysis.getErrors", params);
  }

  RequestData sendAnalysisGetHover(String file, int offset) {
    var params = new AnalysisGetHoverParams(file, offset).toJson();
    return _send("analysis.getHover", params);
  }

  RequestData sendAnalysisGetLibraryDependencies() {
    return _send("analysis.getLibraryDependencies", null);
  }

  RequestData sendAnalysisGetNavigation(String file, int offset, int length) {
    var params = new AnalysisGetNavigationParams(file, offset, length).toJson();
    return _send("analysis.getNavigation", params);
  }

  RequestData sendAnalysisGetReachableSources(String file) {
    var params = new AnalysisGetReachableSourcesParams(file).toJson();
    return _send("analysis.getReachableSources", params);
  }

  void sendAnalysisReanalyze() {
    var params = new AnalysisReanalyzeParams().toJson();
    _send("analysis.reanalyze", params);
  }

  void sendAnalysisSetAnalysisRoots(
      List<String> included, List<String> excluded,
      {Map<String, String> packageRoots}) {
    _analysisRootIncludes = included;
    var params = new AnalysisSetAnalysisRootsParams(included, excluded,
            packageRoots: packageRoots)
        .toJson();
    _send("analysis.setAnalysisRoots", params);
  }

  void sendAnalysisSetGeneralSubscriptions(
      List<GeneralAnalysisService> subscriptions) {
    var params =
        new AnalysisSetGeneralSubscriptionsParams(subscriptions).toJson();
    _send("analysis.setGeneralSubscriptions", params);
  }

  void sendAnalysisSetPriorityFiles(List<String> files) {
    var params = new AnalysisSetPriorityFilesParams(files).toJson();
    _send("analysis.setPriorityFiles", params);
  }

  void sendAnalysisSetSubscriptions(
      Map<AnalysisService, List<String>> subscriptions) {
    var params = new AnalysisSetSubscriptionsParams(subscriptions).toJson();
    _send("analysis.setSubscriptions", params);
  }

  void sendAnalysisUpdateContent(Map<String, dynamic> files) {
    files.forEach((String path, dynamic overlay) {
      if (overlay is AddContentOverlay) {
        filesWithOverlays.add(path);
      } else if (overlay is RemoveContentOverlay) {
        filesWithOverlays.remove(path);
      }
    });
    var params = new AnalysisUpdateContentParams(files).toJson();
    _send('analysis.updateContent', params);
  }

  void sendAnalysisUpdateOptions(AnalysisOptions options) {
    var params = new AnalysisUpdateOptionsParams(options).toJson();
    _send("analysis.updateOptions", params);
  }

  void sendCompletionGetSuggestions(String file, int offset) {
    var params = new CompletionGetSuggestionsParams(file, offset).toJson();
    _send("completion.getSuggestions", params);
  }

  RequestData sendDiagnosticGetDiagnostics() {
    return _send("diagnostic.getDiagnostics", null);
  }

  RequestData sendEditFormat(
      String file, int selectionOffset, int selectionLength,
      {int lineLength}) {
    var params = new EditFormatParams(file, selectionOffset, selectionLength,
            lineLength: lineLength)
        .toJson();
    return _send("edit.format", params);
  }

  RequestData sendEditGetAssists(String file, int offset, int length) {
    var params = new EditGetAssistsParams(file, offset, length).toJson();
    return _send("edit.getAssists", params);
  }

  RequestData sendEditGetAvailableRefactorings(
      String file, int offset, int length) {
    var params =
        new EditGetAvailableRefactoringsParams(file, offset, length).toJson();
    return _send("edit.getAvailableRefactorings", params);
  }

  RequestData sendEditGetFixes(String file, int offset) {
    var params = new EditGetFixesParams(file, offset).toJson();
    return _send("edit.getFixes", params);
  }

  RequestData sendEditGetRefactoring(RefactoringKind kind, String file,
      int offset, int length, bool validateOnly,
      {RefactoringOptions options}) {
    var params = new EditGetRefactoringParams(
            kind, file, offset, length, validateOnly,
            options: options)
        .toJson();
    return _send("edit.getRefactoring", params);
  }

  RequestData sendEditOrganizeDirectives(String file) {
    var params = new EditOrganizeDirectivesParams(file).toJson();
    return _send("edit.organizeDirectives", params);
  }

  RequestData sendEditSortMembers(String file) {
    var params = new EditSortMembersParams(file).toJson();
    return _send("edit.sortMembers", params);
  }

  RequestData sendExecutionCreateContext(String contextRoot) {
    var params = new ExecutionCreateContextParams(contextRoot).toJson();
    return _send("execution.createContext", params);
  }

  RequestData sendExecutionDeleteContext(String id) {
    var params = new ExecutionDeleteContextParams(id).toJson();
    return _send("execution.deleteContext", params);
  }

  RequestData sendExecutionMapUri(String id, {String file, String uri}) {
    var params = new ExecutionMapUriParams(id, file: file, uri: uri).toJson();
    return _send("execution.mapUri", params);
  }

  RequestData sendExecutionSetSubscriptions(
      List<ExecutionService> subscriptions) {
    var params = new ExecutionSetSubscriptionsParams(subscriptions).toJson();
    return _send("execution.setSubscriptions", params);
  }

  void sendSearchFindElementReferences(
      String file, int offset, bool includePotential) {
    var params =
        new SearchFindElementReferencesParams(file, offset, includePotential)
            .toJson();
    _send("search.findElementReferences", params);
  }

  void sendSearchFindMemberDeclarations(String name) {
    var params = new SearchFindMemberDeclarationsParams(name).toJson();
    _send("search.findMemberDeclarations", params);
  }

  void sendSearchFindMemberReferences(String name) {
    var params = new SearchFindMemberReferencesParams(name).toJson();
    _send("search.findMemberReferences", params);
  }

  void sendSearchFindTopLevelDeclarations(String pattern) {
    var params = new SearchFindTopLevelDeclarationsParams(pattern).toJson();
    _send("search.findTopLevelDeclarations", params);
  }

  void sendSearchGetTypeHierarchy(String file, int offset, {bool superOnly}) {
    var params =
        new SearchGetTypeHierarchyParams(file, offset, superOnly: superOnly)
            .toJson();
    _send("search.getTypeHierarchy", params);
  }

  RequestData sendServerGetVersion() {
    return _send("server.getVersion", null);
  }

  void sendServerSetSubscriptions(List<ServerService> subscriptions) {
    var params = new ServerSetSubscriptionsParams(subscriptions).toJson();
    _send("server.setSubscriptions", params);
  }

  void sendServerShutdown() {
    _send("server.shutdown", null);
  }

  /**
   * Start the server and listen for communications from it.
   *
   * If [checked] is `true`, the server's VM will be running in checked mode.
   *
   * If [diagnosticPort] is not `null`, the server will serve status pages to
   * the specified port.
   *
   * If [profileServer] is `true`, the server will be started with "--observe"
   * and "--pause-isolates-on-exit", allowing the observatory to be used.
   *
   * If [useAnalysisHighlight2] is `true`, the server will use the new highlight
   * APIs.
   */
  Future<void> start(
      {bool checked = true,
      int diagnosticPort,
      bool profileServer = false,
      String sdkPath,
      int servicesPort,
      bool useAnalysisHighlight2 = false}) async {
    if (_process != null) {
      throw new Exception('Process already started');
    }
    String dartBinary = Platform.executable;
    String rootDir =
        _findRoot(Platform.script.toFilePath(windows: Platform.isWindows));
    String serverPath =
        path.normalize(path.join(rootDir, 'bin', 'server.dart'));
    List<String> arguments = [];
    //
    // Add VM arguments.
    //
    if (profileServer) {
      if (servicesPort == null) {
        arguments.add('--observe');
      } else {
        arguments.add('--observe=$servicesPort');
      }
      arguments.add('--pause-isolates-on-exit');
    } else if (servicesPort != null) {
      arguments.add('--enable-vm-service=$servicesPort');
    }
    if (Platform.packageConfig != null) {
      arguments.add('--packages=${Platform.packageConfig}');
    }
    if (checked) {
      arguments.add('--checked');
    }
    //
    // Add the server executable.
    //
    arguments.add(serverPath);
    //
    // Add server arguments.
    //
    if (diagnosticPort != null) {
      arguments.add('--port');
      arguments.add(diagnosticPort.toString());
    }
    if (sdkPath != null) {
      arguments.add('--sdk=$sdkPath');
    }
    if (useAnalysisHighlight2) {
      arguments.add('--useAnalysisHighlight2');
    }
//    stdout.writeln('Launching $serverPath');
//    stdout.writeln('$dartBinary ${arguments.join(' ')}');
    _process = await Process.start(dartBinary, arguments);
    _process.exitCode.then((int code) {
      if (code != 0) {
        throw new StateError('Server terminated with exit code $code');
      }
    });
    _listenToOutput();
    _serverConnectedCompleter = new Completer<void>();
    return _serverConnectedCompleter.future;
  }

  /**
   * Find the root directory of the analysis_server package by proceeding
   * upward to the 'test' dir, and then going up one more directory.
   */
  String _findRoot(String pathname) {
    while (!['benchmark', 'test'].contains(path.basename(pathname))) {
      String parent = path.dirname(pathname);
      if (parent.length >= pathname.length) {
        throw new Exception("Can't find root directory");
      }
      pathname = parent;
    }
    return path.dirname(pathname);
  }

  /**
   * Handle a [notification] received from the server.
   */
  void _handleNotification(Notification notification) {
    switch (notification.event) {
      case "server.connected":
//        new ServerConnectedParams.fromNotification(notification);
        _serverConnectedCompleter.complete(null);
        break;
      case "server.error":
//        new ServerErrorParams.fromNotification(notification);
        throw new StateError('Server error: ${notification.toJson()}');
        break;
      case "server.status":
        if (_analysisFinishedCompleter != null) {
          ServerStatusParams params =
              new ServerStatusParams.fromNotification(notification);
          var analysis = params.analysis;
          if (analysis != null && !analysis.isAnalyzing) {
            _analysisFinishedCompleter.complete(null);
          }
        }
        break;
      case "analysis.analyzedFiles":
        AnalysisAnalyzedFilesParams params =
            new AnalysisAnalyzedFilesParams.fromNotification(notification);
        _analyzedFiles = params.directories;
        break;
      case "analysis.errors":
        AnalysisErrorsParams params =
            new AnalysisErrorsParams.fromNotification(notification);
        _errorMap.pathMap[params.file] = params.errors;
        break;
      case "analysis.flushResults":
//        new AnalysisFlushResultsParams.fromNotification(notification);
        _errorMap.pathMap.clear();
        break;
      case "analysis.folding":
//        new AnalysisFoldingParams.fromNotification(notification);
        break;
      case "analysis.highlights":
//        new AnalysisHighlightsParams.fromNotification(notification);
        break;
      case "analysis.implemented":
//        new AnalysisImplementedParams.fromNotification(notification);
        break;
      case "analysis.invalidate":
//        new AnalysisInvalidateParams.fromNotification(notification);
        break;
      case "analysis.navigation":
//        new AnalysisNavigationParams.fromNotification(notification);
        break;
      case "analysis.occurrences":
//        new AnalysisOccurrencesParams.fromNotification(notification);
        break;
      case "analysis.outline":
//        new AnalysisOutlineParams.fromNotification(notification);
        break;
      case "analysis.overrides":
//        new AnalysisOverridesParams.fromNotification(notification);
        break;
      case "completion.results":
//        new CompletionResultsParams.fromNotification(notification);
        break;
      case "search.results":
//        new SearchResultsParams.fromNotification(notification);
        break;
      case "execution.launchData":
//        new ExecutionLaunchDataParams.fromNotification(notification);
        break;
      default:
        throw new StateError(
            'Unhandled notification: ${notification.toJson()}');
    }
  }

  /**
   * Handle a [response] received from the server.
   */
  void _handleResponse(Response response) {
    String id = response.id.toString();
    RequestData requestData = _requestDataMap[id];
    requestData.recordResponse(response);
//    switch (requestData.method) {
//      case "analysis.getErrors":
//        break;
//      case "analysis.getHover":
//        break;
//      case "analysis.getLibraryDependencies":
//        break;
//      case "analysis.getNavigation":
//        break;
//      case "analysis.getReachableSources":
//        break;
//      case "analysis.reanalyze":
//        break;
//      case "analysis.setAnalysisRoots":
//        break;
//      case "analysis.setGeneralSubscriptions":
//        break;
//      case "analysis.setPriorityFiles":
//        break;
//      case "analysis.setSubscriptions":
//        break;
//      case 'analysis.updateContent':
//        break;
//      case "analysis.updateOptions":
//        break;
//      case "completion.getSuggestions":
//        break;
//      case "diagnostic.getDiagnostics":
//        break;
//      case "edit.format":
//        break;
//      case "edit.getAssists":
//        break;
//      case "edit.getAvailableRefactorings":
//        break;
//      case "edit.getFixes":
//        break;
//      case "edit.getRefactoring":
//        break;
//      case "edit.organizeDirectives":
//        break;
//      case "edit.sortMembers":
//        break;
//      case "execution.createContext":
//        break;
//      case "execution.deleteContext":
//        break;
//      case "execution.mapUri":
//        break;
//      case "execution.setSubscriptions":
//        break;
//      case "search.findElementReferences":
//        break;
//      case "search.findMemberDeclarations":
//        break;
//      case "search.findMemberReferences":
//        break;
//      case "search.findTopLevelDeclarations":
//        break;
//      case "search.getTypeHierarchy":
//        break;
//      case "server.getVersion":
//        break;
//      case "server.setSubscriptions":
//        break;
//      case "server.shutdown":
//        break;
//      default:
//        throw new StateError('Unhandled response: ${response.toJson()}');
//    }
  }

  /**
   * Handle a [line] of input read from stderr.
   */
  void _handleStdErr(String line) {
    String trimmedLine = line.trim();
    logger?.log(fromStderr, '$trimmedLine');
    throw new StateError('Message received on stderr: "$trimmedLine"');
  }

  /**
   * Handle a [line] of input read from stdout.
   */
  void _handleStdOut(String line) {
    /**
     * Cast the given [value] to a Map, or throw an [ArgumentError] if the value
     * cannot be cast.
     */
    Map asMap(Object value) {
      if (value is Map) {
        return value;
      }
      throw new ArgumentError('Expected a Map, found a ${value.runtimeType}');
    }

    String trimmedLine = line.trim();
    if (trimmedLine.isEmpty ||
        trimmedLine.startsWith('Observatory listening on ')) {
      return;
    }
    logger?.log(fromServer, '$trimmedLine');
    Map message = asMap(json.decoder.convert(trimmedLine));
    if (message.containsKey('id')) {
      // The message is a response.
      Response response = new Response.fromJson(message);
      _handleResponse(response);
    } else {
      // The message is a notification.
      Notification notification = new Notification.fromJson(message);
      String event = notification.event;
      _notificationCountMap[event] = (_notificationCountMap[event] ?? 0) + 1;
      _handleNotification(notification);
    }
  }

  /**
   * Start listening to output from the server.
   */
  void _listenToOutput() {
    /**
     * Install the given [handler] to listen to transformed output from the
     * given [stream].
     */
    void installHandler(Stream<List<int>> stream, handler(String line)) {
      stream
          .transform((new Utf8Codec()).decoder)
          .transform(new LineSplitter())
          .listen(handler);
    }

    installHandler(_process.stdout, _handleStdOut);
    installHandler(_process.stderr, _handleStdErr);
  }

  /**
   * Send a command to the server. An 'id' will be automatically assigned.
   */
  RequestData _send(String method, Map<String, dynamic> params,
      {void onResponse(Response response)}) {
    String id = '${_nextId++}';
    RequestData requestData = new RequestData(id, method, params, currentTime);
    _requestDataMap[id] = requestData;
    Map<String, dynamic> command = <String, dynamic>{
      'id': id,
      'method': method
    };
    if (params != null) {
      command['params'] = params;
    }
    String line = json.encode(command);
    _process.stdin.add(utf8.encoder.convert('$line\n'));
    logger?.log(fromClient, '$line');
    return requestData;
  }
}
