// 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/plugin/protocol/protocol.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;
  }

  /**
   * Compare the this error map with the state captured in the given [errorMap].
   * Throw an exception if the two maps do not agree.
   */
  String expectErrorMap(ErrorMap errorMap) {
    StringBuffer buffer = new StringBuffer();
    _ErrorComparator comparator = new _ErrorComparator(buffer);
    comparator.compare(pathMap, errorMap.pathMap);
    if (buffer.length > 0) {
      return buffer.toString();
    }
    return null;
  }
}

/**
 * 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 betwee 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>[];

  /**
   * The analysis roots that are excluded.
   */
  List<String> _analysisRootExcludes = <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<Null> _analysisFinishedCompleter;

  /**
   * The completer that will be completed the next time a 'server.connected'
   * notification is received from the server.
   */
  Completer<Null> _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();
    }
    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({List<String> roots}) {
    var params = new AnalysisReanalyzeParams(roots: roots).toJson();
    _send("analysis.reanalyze", params);
  }

  void sendAnalysisSetAnalysisRoots(
      List<String> included, List<String> excluded,
      {Map<String, String> packageRoots}) {
    _analysisRootIncludes = included;
    _analysisRootExcludes = excluded;
    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 [debugServer] is `true`, the server will be started with "--debug",
   * allowing a debugger to be attached.
   *
   * If [diagnosticPort] is not `null`, the server will serve status pages to
   * the specified port.
   *
   * If [enableNewAnalysisDriver] is `true`, the server will use the new
   * analysis driver.
   *
   * 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<Null> start(
      {bool checked: true,
      bool debugServer: false,
      int diagnosticPort,
      bool enableNewAnalysisDriver: false,
      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 (debugServer) {
      arguments.add('--debug');
    }
    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.packageRoot != null) {
      arguments.add('--package-root=${Platform.packageRoot}');
    }
    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');
    }
    if (enableNewAnalysisDriver) {
      arguments.add('--enable-new-analysis-driver');
    }
//    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();
    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;
  }
}

/**
 * A utility class used to compare two sets of errors.
 */
class _ErrorComparator {
  /**
   * An empty list of analysis errors.
   */
  static final List<AnalysisError> NO_ERRORS = <AnalysisError>[];

  /**
   * The buffer to which an error description will be written if any of the
   * files have different errors than are expected.
   */
  final StringBuffer buffer;

  /**
   * Initialize a newly created comparator to write to the given [buffer].
   */
  _ErrorComparator(this.buffer);

  /**
   * Compare the [actualErrorMap] and the [expectedErrorMap], writing a
   * description to the [buffer] if they are not the same. The error maps are
   * expected to be maps from absolute file paths to the list of actual or
   * expected errors.
   */
  void compare(Map<String, List<AnalysisError>> actualErrorMap,
      Map<String, List<AnalysisError>> expectedErrorMap) {
    Set<String> allFiles = new HashSet();
    allFiles.addAll(actualErrorMap.keys);
    allFiles.addAll(expectedErrorMap.keys);
    List<String> sortedFiles = allFiles.toList()..sort();
    for (String filePath in sortedFiles) {
      List<AnalysisError> actualErrors = actualErrorMap[filePath];
      List<AnalysisError> expectedErrors = expectedErrorMap[filePath];
      _compareLists(
          filePath, actualErrors ?? NO_ERRORS, expectedErrors ?? NO_ERRORS);
    }
  }

  /**
   * Compare the [actualErrors] and [expectedErrors], writing a description to
   * the [buffer] if they are not the same.
   */
  void _compareLists(String filePath, List<AnalysisError> actualErrors,
      List<AnalysisError> expectedErrors) {
    List<AnalysisError> remainingExpected =
        new List<AnalysisError>.from(expectedErrors);
    for (AnalysisError actualError in actualErrors) {
      AnalysisError expectedError = _findError(remainingExpected, actualError);
      if (expectedError == null) {
        _writeReport(filePath, actualErrors, expectedErrors);
        return;
      }
      remainingExpected.remove(expectedError);
    }
    if (remainingExpected.isNotEmpty) {
      _writeReport(filePath, actualErrors, expectedErrors);
    }
  }

  /**
   * Return `true` if the [firstError] and the [secondError] are equivalent.
   */
  bool _equalErrors(AnalysisError firstError, AnalysisError secondError) =>
      firstError.severity == secondError.severity &&
      firstError.type == secondError.type &&
      _equalLocations(firstError.location, secondError.location) &&
      firstError.message == secondError.message;

  /**
   * Return `true` if the [firstLocation] and the [secondLocation] are
   * equivalent.
   */
  bool _equalLocations(Location firstLocation, Location secondLocation) =>
      firstLocation.file == secondLocation.file &&
      firstLocation.offset == secondLocation.offset &&
      firstLocation.length == secondLocation.length;

  /**
   * Search through the given list of [errors] for an error that is equal to the
   * [targetError]. If one is found, return it, otherwise return `null`.
   */
  AnalysisError _findError(
      List<AnalysisError> errors, AnalysisError targetError) {
    for (AnalysisError error in errors) {
      if (_equalErrors(error, targetError)) {
        return error;
      }
    }
    return null;
  }

  /**
   * Write the given list of [errors], preceded by a header beginning with the
   * given [prefix].
   */
  void _writeErrors(String prefix, List<AnalysisError> errors) {
    buffer.write(prefix);
    buffer.write(errors.length);
    buffer.write(' errors:');
    for (AnalysisError error in errors) {
      buffer.writeln();
      Location location = error.location;
      int offset = location.offset;
      buffer.write('    ');
      buffer.write(location.file);
      buffer.write(' (');
      buffer.write(offset);
      buffer.write('..');
      buffer.write(offset + location.length);
      buffer.write(') ');
      buffer.write(error.severity);
      buffer.write(', ');
      buffer.write(error.type);
      buffer.write(' : ');
      buffer.write(error.message);
    }
  }

  /**
   * Write a report of the differences between the [actualErrors] and the
   * [expectedErrors]. The errors are reported as being from the file at the
   * given [filePath].
   */
  void _writeReport(String filePath, List<AnalysisError> actualErrors,
      List<AnalysisError> expectedErrors) {
    if (buffer.length > 0) {
      buffer.writeln();
      buffer.writeln();
    }
    buffer.writeln(filePath);
    _writeErrors('  Expected ', expectedErrors);
    buffer.writeln();
    _writeErrors('  Found ', actualErrors);
  }
}
