// Copyright (c) 2017, 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 'dart:convert';
import 'dart:io';

/// Type of callbacks used to process notification.
typedef void NotificationProcessor(String event, Map<String, Object> params);

/// Instances of the class [AnalysisServerClient] manage a connection to an
/// [AnalysisServer] process, and facilitate communication to and from the
/// client/user.
class AnalysisServerClient {
  /// AnalysisServer process object, or null if the server has been shut down.
  final Process _process;

  /// Commands that have been sent to the server but not yet acknowledged,
  /// and the [Completer] objects which should be completed when
  /// acknowledgement is received.
  final Map<String, Completer> _pendingCommands = <String, Completer>{};

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

  AnalysisServerClient(this._process);

  /// Return a future that will complete when all commands that have been
  /// sent to the server so far have been flushed to the OS buffer.
  Future<Null> flushCommands() {
    return _process.stdin.flush();
  }

  /// Force kill the server. Returns exit code future.
  Future<int> kill() {
    _process.kill();
    return _process.exitCode;
  }

  void listenToOutput({NotificationProcessor notificationProcessor}) {
    _process.stdout
        .transform((new Utf8Codec()).decoder)
        .transform(new LineSplitter())
        .listen((String line) {
      String trimmedLine = line.trim();
      if (trimmedLine.startsWith('Observatory listening on ')) {
        return;
      }
      final result = json.decoder.convert(trimmedLine) as Map;
      if (result.containsKey('id')) {
        final id = result['id'] as String;
        final completer = _pendingCommands.remove(id);

        if (result.containsKey('error')) {
          completer.completeError(new ServerErrorMessage(result['error']));
        } else {
          completer.complete(result['result']);
        }
      } else if (notificationProcessor != null && result.containsKey('event')) {
        // Message is a notification. It should have an event and possibly
        // params.
        notificationProcessor(result['event'], result['params']);
      }
    });
  }

  /// Sends a command to the server. An 'id' will be automatically assigned.
  /// The returned [Future] will be completed when the server acknowledges
  /// the command with a response. If the server acknowledges the command
  /// with a normal (non-error) response, the future will be completed
  /// with the 'result' field from the response. If the server acknowledges
  /// the command with an error response, the future will be completed with an
  /// error.
  Future send(String method, Map<String, dynamic> params) {
    String id = '${_nextId++}';
    Map<String, dynamic> command = <String, dynamic>{
      'id': id,
      'method': method
    };
    if (params != null) {
      command['params'] = params;
    }
    Completer completer = new Completer();
    _pendingCommands[id] = completer;
    String commandAsJson = json.encode(command);
    _process.stdin.add(utf8.encoder.convert('$commandAsJson\n'));
    return completer.future;
  }
}

class ServerErrorMessage {
  final Map errorJson;

  ServerErrorMessage(this.errorJson);

  String get code => errorJson['code'].toString();
  String get message => errorJson['message'];
  String get stackTrace => errorJson['stackTrace'];
}
