// Copyright (c) 2020, 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';

import 'package:analysis_server_client/listener/server_listener.dart';
import 'package:analysis_server_client/protocol.dart';

///
/// Add server arguments.
///
/// TODO(danrubel): Consider moving all cmdline argument consts
/// out of analysis_server and into analysis_server_client.
List<String> getServerArguments({
  String? clientId,
  String? clientVersion,
  int? diagnosticPort,
  String? instrumentationLogFile,
  String? sdkPath,
  bool suppressAnalytics = true,
  bool useAnalysisHighlight2 = false,
}) {
  var arguments = <String>[];

  if (clientId != null) {
    arguments.add('--client-id');
    arguments.add(clientId);
  }
  if (clientVersion != null) {
    arguments.add('--client-version');
    arguments.add(clientVersion);
  }
  if (suppressAnalytics) {
    arguments.add('--suppress-analytics');
  }
  if (diagnosticPort != null) {
    arguments.add('--port');
    arguments.add(diagnosticPort.toString());
  }
  if (instrumentationLogFile != null) {
    arguments.add('--instrumentation-log-file=$instrumentationLogFile');
  }
  if (sdkPath != null) {
    arguments.add('--sdk=$sdkPath');
  }
  if (useAnalysisHighlight2) {
    arguments.add('--useAnalysisHighlight2');
  }
  return arguments;
}

/// A function via which data can be sent to a started server.
typedef CommandSender = void Function(List<int> utf8bytes);

/// Type of callbacks used to process notifications.
typedef NotificationProcessor = void Function(Notification notification);

/// Implementations of the class [ServerBase] manage an analysis server,
/// and facilitate communication to and from the server.
///
/// Clients outside of this package may not extend or implement this class.
abstract class ServerBase {
  /// Replicate all data from the server process to stdout/stderr, when true.
  final bool _stdioPassthrough;

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

  /// If not `null`, [_listener] will be sent information
  /// about interactions with the server.
  final ServerListener? _listener;

  /// 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 _pendingCommands = <String, Completer<Map<String, Object?>?>>{};

  new({this._listener, this._stdioPassthrough = false});

  ServerListener? get listener => _listener;

  /// If the implementation of [ServerBase] captures an error stream,
  /// it can use this to forward the errors to [listener] and [stderr] if
  /// appropriate.
  void errorProcessor(
    String line,
    NotificationProcessor? notificationProcessor,
  ) {
    if (_stdioPassthrough) stderr.writeln(line);
    var trimmedLine = line.trim();
    listener?.errorMessage(trimmedLine);
  }

  /// Force kill the server. Returns a future that completes when the server
  /// stops.
  Future kill({String reason = 'none'});

  /// Start listening to output from the server,
  /// and deliver notifications to [notificationProcessor].
  void listenToOutput({NotificationProcessor notificationProcessor});

  /// Handle a (possibly) json encoded object, completing the [Completer] in
  /// [_pendingCommands] corresponding to the response.  Reports problems in
  /// decoding or message synchronization using [listener], and replicates
  /// raw data to [stdout] as appropriate.
  void outputProcessor(
    String line,
    NotificationProcessor? notificationProcessor,
  ) {
    if (_stdioPassthrough) stdout.writeln(line);
    var trimmedLine = line.trim();

    // Guard against lines like:
    //   {"event":"server.connected","params":{...}}The Dart VM service is listening on ...
    const dartVMServiceMessage = 'The Dart VM service is listening on ';
    if (trimmedLine.contains(dartVMServiceMessage)) {
      trimmedLine = trimmedLine
          .substring(0, trimmedLine.indexOf(dartVMServiceMessage))
          .trim();
    }
    if (trimmedLine.isEmpty) {
      return;
    }

    listener?.messageReceived(trimmedLine);
    Map<String, Object?> message;
    try {
      message = json.decoder.convert(trimmedLine);
    } catch (exception) {
      listener?.badMessage(trimmedLine, exception);
      return;
    }

    // Handle response.
    final id = message[Response.ID];
    if (id != null) {
      final completer = _pendingCommands.remove(id);
      if (completer == null) {
        listener?.unexpectedResponse(message, id);
        return;
      }

      final errorJson = message[Response.ERROR];
      if (errorJson != null) {
        completer.completeError(
          RequestError.fromJson(ResponseDecoder(null), '.error', errorJson),
        );
        return;
      }

      final resultJson = message[Response.RESULT];
      if (resultJson is Map<String, Object?>?) {
        completer.complete(resultJson);
        return;
      }

      listener?.unexpectedResponseFormat(message);
      return;
    }

    // Handle notification.
    final event = message[Notification.EVENT];
    if (event is String) {
      final paramsJson = message[Notification.PARAMS];
      if (paramsJson is Map<String, Object?>) {
        if (notificationProcessor != null) {
          notificationProcessor(Notification(event, paramsJson));
        }
      } else {
        listener?.unexpectedNotificationFormat(message);
      }
      return;
    }

    listener?.unexpectedMessage(message);
  }

  /// Send 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<Map<String, Object?>?> send(
    String method,
    Map<String, Object?>? params,
  );

  /// Encodes a request for transmission and sends it as a utf8 encoded byte
  /// string with [sendWith].
  Future<Map<String, Object?>?> sendCommandWith(
    String method,
    Map<String, Object?>? params,
    CommandSender sendWith,
  ) {
    var id = '${_nextId++}';
    var command = <String, dynamic>{Request.ID: id, Request.METHOD: method};
    if (params != null) {
      command[Request.PARAMS] = params;
    }
    final completer = Completer<Map<String, Object?>?>();
    _pendingCommands[id] = completer;
    var line = json.encode(command);
    listener?.requestSent(line);
    sendWith(utf8.encode('$line\n'));
    return completer.future;
  }

  /// Start the server.  The returned future completes when the server
  /// is started and it is valid to call [listenToOutput].
  Future start({
    String clientId,
    String clientVersion,
    int diagnosticPort,
    String instrumentationLogFile,
    String sdkPath,
    bool suppressAnalytics,
    bool useAnalysisHighlight2,
  });

  /// Attempt to gracefully shutdown the server.
  /// If that fails, then force it to shut down.
  Future stop({Duration timeLimit});
}
