// 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?>?>>{};

  ServerBase({ServerListener? listener, bool stdioPassthrough = false})
      : _listener = listener,
        _stdioPassthrough = stdioPassthrough;

  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.encoder.convert('$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});
}
