// 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.

/// @docImport 'package:analysis_server/src/analysis_server.dart';
library;

import 'dart:async';
import 'dart:convert';

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/src/channel/channel.dart';
import 'package:analysis_server/src/plugin/plugin_manager.dart';
import 'package:analyzer/dart/analysis/context_root.dart' as analyzer;
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin;
import 'package:watcher/watcher.dart';

/// A mock [ServerCommunicationChannel] for testing [AnalysisServer].
class MockServerChannel implements ServerCommunicationChannel {
  /// A controller for the stream of requests and responses from the client to
  /// the server.
  ///
  /// Messages added to this stream should be converted to/from JSON to ensure
  /// they are fully serialized/deserialized as they would be in a real server
  /// otherwise tests may receive real instances where in reality they would be
  /// maps.
  StreamController<RequestOrResponse> requestController =
      StreamController<RequestOrResponse>();

  /// A controller for the stream of requests and responses from the server to
  /// the client.
  ///
  /// Messages added to this stream should be converted to/from JSON to ensure
  /// they are fully serialized/deserialized as they would be in a real server
  /// otherwise tests may receive real instances where in reality they would be
  /// maps.
  StreamController<RequestOrResponse> responseController =
      StreamController<RequestOrResponse>.broadcast();

  /// A controller for the stream of notifications from the server to the
  /// client.
  ///
  /// Unlike [requestController] and [responseController], notifications added
  /// here are not round-tripped through JSON but instead have real class
  /// instances as their `params`. This is because they are only used by tests
  /// which will cast and/or switch on the types for convenience.
  StreamController<Notification> notificationController =
      StreamController<Notification>.broadcast(sync: true);

  Completer<Response>? errorCompleter;

  List<Response> responsesReceived = [];
  List<Notification> notificationsReceived = [];
  List<Request> serverRequestsSent = [];

  bool _closed = false;

  String? name;

  /// True if we are printing out messages exchanged with the server.
  final bool printMessages;

  MockServerChannel({bool? printMessages})
    : printMessages = printMessages ?? false;

  /// Return the broadcast stream of notifications.
  Stream<Notification> get notifications {
    return notificationController.stream;
  }

  @override
  Stream<RequestOrResponse> get requests => requestController.stream;

  /// Return the broadcast stream of server-to-client requests.
  Stream<Request> get serverToClientRequests {
    return responseController.stream.where((r) => r is Request).cast<Request>();
  }

  @override
  void close() {
    _closed = true;
  }

  @override
  void sendNotification(Notification notification) {
    // Don't deliver notifications after the connection is closed.
    if (_closed) {
      return;
    }

    notificationsReceived.add(notification);
    notificationController.add(notification);

    var errorCompleter = this.errorCompleter;
    if (errorCompleter != null && notification.event == 'server.error') {
      var params = notification.params!;
      print('[server.error] test: $name message: ${params['message']}');
      errorCompleter.completeError(
        ServerError(params['message'] as String),
        StackTrace.fromString(params['stackTrace'] as String),
      );
    }
  }

  @override
  void sendRequest(Request request) {
    var jsonString = jsonEncode(request.toJson());
    if (printMessages) {
      print('<== $jsonString');
    }

    // Round-trip via JSON to ensure all types are fully serialized as they
    // would be in a real setup.
    request = Request.fromJson(jsonDecode(jsonString) as Map<String, Object?>)!;

    serverRequestsSent.add(request);
    responseController.add(request);
  }

  @override
  void sendResponse(Response response) {
    // Don't deliver responses after the connection is closed.
    if (_closed) {
      return;
    }

    var jsonString = jsonEncode(response.toJson());
    if (printMessages) {
      print('<== $jsonString');
    }

    // Round-trip via JSON to ensure all types are fully serialized as they
    // would be in a real setup.
    response =
        Response.fromJson(jsonDecode(jsonString) as Map<String, Object?>)!;

    responsesReceived.add(response);
    responseController.add(response);
  }

  /// Send the given [request] to the server as if it had been sent from the
  /// client, and return a future that will complete when a response associated
  /// with the [request] has been received.
  ///
  /// The value of the future will be the received response.
  Future<Response> simulateRequestFromClient(Request request) async {
    if (_closed) {
      throw Exception('simulateRequestFromClient after connection closed');
    }

    var jsonString = jsonEncode(request.toJson());
    if (printMessages) {
      print('==> $jsonString');
    }

    // Round-trip via JSON to ensure all types are fully serialized as they
    // would be in a real setup.
    request = Request.fromJson(jsonDecode(jsonString) as Map<String, Object?>)!;

    requestController.add(request);
    var response = await waitForResponse(request);

    // Round-trip via JSON to ensure all types are fully serialized as they
    // would be in a real setup.
    response =
        Response.fromJson(
          jsonDecode(jsonEncode(response)) as Map<String, Object?>,
        )!;

    return response;
  }

  /// Send the given [response] to the server as if it had been sent from the
  /// client.
  void simulateResponseFromClient(Response response) {
    // No further requests should be sent after the connection is closed.
    if (_closed) {
      throw Exception('simulateRequestFromClient after connection closed');
    }

    var jsonString = jsonEncode(response.toJson());
    if (printMessages) {
      print('==> $jsonString');
    }

    // Round-trip via JSON to ensure all types are fully serialized as they
    // would be in a real setup.
    response =
        Response.fromJson(jsonDecode(jsonString) as Map<String, Object?>)!;

    requestController.add(response);
  }

  /// Return a future that will complete when a response associated with the
  /// given [request] has been received. The value of the future will be the
  /// received response.
  ///
  /// Unlike [simulateRequestFromClient], this method assumes that the [request]
  /// has already been sent to the server.
  Future<Response> waitForResponse(Request request) {
    var id = request.id;
    return responseController.stream
        .where((r) => r is Response)
        .cast<Response>()
        .firstWhere((response) => response.id == id);
  }
}

class ServerError implements Exception {
  final String message;

  ServerError(this.message);

  @override
  String toString() {
    return 'Server Error: $message';
  }
}

/// A plugin manager that simulates broadcasting requests to plugins by
/// hard-coding the responses.
class TestPluginManager implements PluginManager {
  plugin.AnalysisSetPriorityFilesParams? analysisSetPriorityFilesParams;
  plugin.AnalysisSetSubscriptionsParams? analysisSetSubscriptionsParams;
  plugin.AnalysisUpdateContentParams? analysisUpdateContentParams;
  plugin.RequestParams? broadcastedRequest;
  Map<PluginInfo, Future<plugin.Response>>? broadcastResults;
  Map<PluginInfo, Future<plugin.Response>>? Function(plugin.RequestParams)?
  handleRequest;
  Map<analyzer.ContextRoot, List<String>> contextRootPlugins = {};

  @override
  List<PluginInfo> plugins = [];

  @override
  Completer<void> initializedCompleter = Completer();

  StreamController<void> pluginsChangedController =
      StreamController.broadcast();

  @override
  Stream<void> get pluginsChanged => pluginsChangedController.stream;

  @override
  Future<void> addPluginToContextRoot(
    analyzer.ContextRoot contextRoot,
    String path, {
    required bool isLegacyPlugin,
  }) async {
    contextRootPlugins.putIfAbsent(contextRoot, () => []).add(path);
  }

  @override
  Map<PluginInfo, Future<plugin.Response>> broadcastRequest(
    plugin.RequestParams params, {
    analyzer.ContextRoot? contextRoot,
  }) {
    broadcastedRequest = params;
    return handleRequest?.call(params) ?? broadcastResults ?? {};
  }

  @override
  Future<List<Future<plugin.Response>>> broadcastWatchEvent(
    WatchEvent watchEvent,
  ) async {
    return [];
  }

  @override
  dynamic noSuchMethod(Invocation invocation) =>
      throw Exception('Unexpected invocation of ${invocation.memberName}');

  @override
  void removedContextRoot(analyzer.ContextRoot contextRoot) {
    contextRootPlugins.remove(contextRoot);
  }

  @override
  Future<void> restartPlugins() async {
    // Nothing to restart.
  }

  @override
  void setAnalysisSetPriorityFilesParams(
    plugin.AnalysisSetPriorityFilesParams params,
  ) {
    analysisSetPriorityFilesParams = params;
  }

  @override
  void setAnalysisSetSubscriptionsParams(
    plugin.AnalysisSetSubscriptionsParams params,
  ) {
    analysisSetSubscriptionsParams = params;
  }

  @override
  void setAnalysisUpdateContentParams(
    plugin.AnalysisUpdateContentParams params,
  ) {
    analysisUpdateContentParams = params;
  }
}
