// 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:collection';

import 'package:analysis_server/lsp_protocol/protocol.dart' as lsp;
import 'package:analysis_server/protocol/protocol_generated.dart' as server;
import 'package:analysis_server/src/channel/channel.dart';
import 'package:analysis_server/src/legacy_analysis_server.dart';
import 'package:analysis_server/src/lsp/client_capabilities.dart';
import 'package:analysis_server/src/lsp/mapping.dart' as lsp;
import 'package:analysis_server/src/plugin/result_collector.dart';
import 'package:analysis_server/src/plugin/result_converter.dart';
import 'package:analysis_server/src/plugin/result_merger.dart';
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:analyzer_plugin/src/utilities/client_uri_converter.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart';

/// The object used to coordinate the results of notifications from the analysis
/// server and multiple plugins.
abstract class AbstractNotificationManager {
  /// The identifier used to identify results from the server.
  static const String serverId = 'server';

  /// The current URI converter used for translating URIs/Paths for the
  /// server-client side of communication.
  ClientUriConverter? uriConverter;

  /// The path context.
  final Context _pathContext;

  /// A list of the paths of files and directories that are included for
  /// analysis.
  List<String> _includedPaths = <String>[];

  /// A list of the paths of files and directories that are excluded from
  /// analysis.
  List<String> _excludedPaths = <String>[];

  /// The current set of subscriptions to which the client has subscribed.
  Map<server.AnalysisService, Set<String>> _currentSubscriptions =
      <server.AnalysisService, Set<String>>{};

  /// The collector being used to collect the analysis errors from the plugins.
  // TODO(brianwilkerson): Consider the possibility of not passing the predicate
  //  in to the collector, but instead to the testing in this class.
  late final ResultCollector<List<AnalysisError>> errors =
      ResultCollector<List<AnalysisError>>(serverId, predicate: _isIncluded);

  /// The collector being used to collect the folding regions from the plugins.
  final ResultCollector<List<FoldingRegion>> folding;

  /// The collector being used to collect the highlight regions from the
  /// plugins.
  final ResultCollector<List<HighlightRegion>> highlights;

  /// The collector being used to collect the navigation parameters from the
  /// plugins.
  final ResultCollector<server.AnalysisNavigationParams> _navigation;

  /// The collector being used to collect the occurrences from the plugins.
  final ResultCollector<List<Occurrences>> _occurrences;

  /// The collector being used to collect the outlines from the plugins.
  final ResultCollector<List<Outline>> _outlines;

  /// The object used to convert results.
  final ResultConverter _converter = ResultConverter();

  /// The object used to merge results.
  final ResultMerger merger = ResultMerger();

  /// Whether the plugin isolate is currently analyzing, as per its last status
  /// notification.
  bool pluginStatusAnalyzing = false;

  /// The controller that is notified when analysis status changes.
  final StreamController<bool> _analysisStatusChangesController =
      StreamController.broadcast();

  final StreamController<PluginPrint> _pluginPrintController =
      StreamController.broadcast();

  /// Initialize a newly created notification manager.
  new(this._pathContext)
    : folding = ResultCollector<List<FoldingRegion>>(serverId),
      highlights = ResultCollector<List<HighlightRegion>>(serverId),
      _navigation = ResultCollector<server.AnalysisNavigationParams>(serverId),
      _occurrences = ResultCollector<List<Occurrences>>(serverId),
      _outlines = ResultCollector<List<Outline>>(serverId);

  /// The Stream of analysis statuses from the plugin isolate.
  ///
  /// Each value emitted represents whether the plugin isolate is analyzing or
  /// not, as per each status notification.
  Stream<bool> get pluginAnalysisStatusChanges =>
      _analysisStatusChangesController.stream;

  /// The Stream of messages printed from the plugin isolate.
  Stream<PluginPrint> get pluginPrints => _pluginPrintController.stream;

  /// Handles a plugin error.
  ///
  /// This amounts to notifying the client, and setting the 'is analyzing'
  /// status to `false`.
  ///
  /// The caller is responsible for logging the error with the instrumentation
  /// service.
  void handlePluginError(String message) {
    _analysisStatusChangesController.add(false /* isAnalyzing */);
    pluginStatusAnalyzing = false;

    sendPluginError(message);
  }

  /// Handle the given [notification] from the plugin with the given [pluginId].
  void handlePluginNotification(
    String pluginId,
    plugin.Notification notification,
  ) {
    var event = notification.event;
    switch (event) {
      case plugin.ANALYSIS_NOTIFICATION_ERRORS:
        var params = plugin.AnalysisErrorsParams.fromNotification(notification);
        recordAnalysisErrors(pluginId, params.file, params.errors);
      case plugin.ANALYSIS_NOTIFICATION_FOLDING:
        var params = plugin.AnalysisFoldingParams.fromNotification(
          notification,
        );
        recordFoldingRegions(pluginId, params.file, params.regions);
      case plugin.ANALYSIS_NOTIFICATION_HIGHLIGHTS:
        var params = plugin.AnalysisHighlightsParams.fromNotification(
          notification,
        );
        recordHighlightRegions(pluginId, params.file, params.regions);
      case plugin.ANALYSIS_NOTIFICATION_NAVIGATION:
        var params = plugin.AnalysisNavigationParams.fromNotification(
          notification,
        );
        recordNavigationParams(
          pluginId,
          params.file,
          _converter.convertAnalysisNavigationParams(params),
        );
      case plugin.ANALYSIS_NOTIFICATION_OCCURRENCES:
        var params = plugin.AnalysisOccurrencesParams.fromNotification(
          notification,
        );
        recordOccurrences(pluginId, params.file, params.occurrences);
      case plugin.ANALYSIS_NOTIFICATION_OUTLINE:
        var params = plugin.AnalysisOutlineParams.fromNotification(
          notification,
        );
        recordOutlines(pluginId, params.file, params.outline);
      case plugin.PLUGIN_NOTIFICATION_ERROR:
        sendPluginErrorNotification(notification);
      case plugin.PLUGIN_NOTIFICATION_STATUS:
        _setPluginStatus(notification);
      case plugin.PLUGIN_NOTIFICATION_PRINT:
        _recordPrint(notification);
    }
  }

  /// Record error information from the plugin with the given [pluginId] for the
  /// file with the given [filePath].
  void recordAnalysisErrors(
    String pluginId,
    String filePath,
    List<AnalysisError> errorData,
  ) {
    if (errors.isCollectingFor(filePath)) {
      errors.putResults(filePath, pluginId, errorData);
      var unmergedErrors = errors.getResults(filePath);
      var mergedErrors = merger.mergeAnalysisErrors(unmergedErrors);
      sendAnalysisErrors(filePath, mergedErrors);
    }
  }

  /// Record folding information from the plugin with the given [pluginId] for
  /// the file with the given [filePath].
  void recordFoldingRegions(
    String pluginId,
    String filePath,
    List<FoldingRegion> foldingData,
  ) {
    if (folding.isCollectingFor(filePath)) {
      folding.putResults(filePath, pluginId, foldingData);
      var unmergedFolding = folding.getResults(filePath);
      var mergedFolding = merger.mergeFoldingRegions(unmergedFolding);
      sendFoldingRegions(filePath, mergedFolding);
    }
  }

  /// Record highlight information from the plugin with the given [pluginId] for
  /// the file with the given [filePath].
  void recordHighlightRegions(
    String pluginId,
    String filePath,
    List<HighlightRegion> highlightData,
  ) {
    if (highlights.isCollectingFor(filePath)) {
      highlights.putResults(filePath, pluginId, highlightData);
      var unmergedHighlights = highlights.getResults(filePath);
      var mergedHighlights = merger.mergeHighlightRegions(unmergedHighlights);
      sendHighlightRegions(filePath, mergedHighlights);
    }
  }

  /// Record navigation information from the plugin with the given [pluginId]
  /// for the file with the given [filePath].
  void recordNavigationParams(
    String pluginId,
    String filePath,
    server.AnalysisNavigationParams navigationData,
  ) {
    if (_navigation.isCollectingFor(filePath)) {
      _navigation.putResults(filePath, pluginId, navigationData);
      var unmergedNavigations = _navigation.getResults(filePath);
      var mergedNavigations = merger.mergeNavigation(unmergedNavigations);
      if (mergedNavigations != null) {
        sendNavigations(mergedNavigations);
      }
    }
  }

  /// Record occurrences information from the plugin with the given [pluginId]
  /// for the file with the given [filePath].
  void recordOccurrences(
    String pluginId,
    String filePath,
    List<Occurrences> occurrencesData,
  ) {
    if (_occurrences.isCollectingFor(filePath)) {
      _occurrences.putResults(filePath, pluginId, occurrencesData);
      var unmergedOccurrences = _occurrences.getResults(filePath);
      var mergedOccurrences = merger.mergeOccurrences(unmergedOccurrences);
      sendOccurrences(filePath, mergedOccurrences);
    }
  }

  /// Record outline information from the plugin with the given [pluginId] for
  /// the file with the given [filePath].
  void recordOutlines(
    String pluginId,
    String filePath,
    List<Outline> outlineData,
  ) {
    if (_outlines.isCollectingFor(filePath)) {
      _outlines.putResults(filePath, pluginId, outlineData);
      var unmergedOutlines = _outlines.getResults(filePath);
      var mergedOutlines = merger.mergeOutline(unmergedOutlines);
      sendOutlines(filePath, mergedOutlines);
    }
  }

  /// Sends errors for a file to the client.
  @visibleForOverriding
  void sendAnalysisErrors(String filePath, List<AnalysisError> mergedErrors);

  /// Sends folding regions for a file to the client.
  @visibleForOverriding
  void sendFoldingRegions(String filePath, List<FoldingRegion> mergedFolding);

  /// Sends highlight regions for a file to the client.
  @visibleForOverriding
  void sendHighlightRegions(
    String filePath,
    List<HighlightRegion> mergedHighlights,
  );

  /// Sends navigation regions for a file to the client.
  @visibleForOverriding
  void sendNavigations(server.AnalysisNavigationParams mergedNavigations);

  /// Sends occurrences for a file to the client.
  @visibleForOverriding
  void sendOccurrences(String filePath, List<Occurrences> mergedOccurrences);

  /// Sends outlines for a file to the client.
  @visibleForOverriding
  void sendOutlines(String filePath, List<Outline> mergedOutlines);

  @visibleForOverriding
  void sendPluginError(String message);

  /// Sends plugin errors to the client.
  @visibleForOverriding
  void sendPluginErrorNotification(plugin.Notification notification);

  /// Set the lists of [included] and [excluded] files.
  void setAnalysisRoots(List<String> included, List<String> excluded) {
    _includedPaths = included;
    _excludedPaths = excluded;
  }

  /// Set the current subscriptions to the given set of [newSubscriptions].
  void setSubscriptions(
    Map<server.AnalysisService, Set<String>> newSubscriptions,
  ) {
    /// Returns the collector associated with the given service, or `null` if
    /// the service is not handled by this manager.
    ResultCollector<Object?>? collectorFor(server.AnalysisService service) {
      return switch (service) {
        server.AnalysisService.FOLDING => folding,
        server.AnalysisService.HIGHLIGHTS => highlights,
        server.AnalysisService.NAVIGATION => _navigation,
        server.AnalysisService.OCCURRENCES => _occurrences,
        server.AnalysisService.OUTLINE => _outlines,
        _ => null,
      };
    }

    Set<server.AnalysisService> services = HashSet<server.AnalysisService>();
    services.addAll(_currentSubscriptions.keys);
    services.addAll(newSubscriptions.keys);
    for (var service in services) {
      var collector = collectorFor(service);
      if (collector != null) {
        var currentPaths = _currentSubscriptions[service];
        var newPaths = newSubscriptions[service];
        if (currentPaths == null) {
          if (newPaths == null) {
            // This should not happen.
            return;
          }
          // All of the [newPaths] need to be added.
          for (var filePath in newPaths) {
            collector.startCollectingFor(filePath);
          }
        } else if (newPaths == null) {
          // All of the [currentPaths] need to be removed.
          for (var filePath in currentPaths) {
            collector.stopCollectingFor(filePath);
          }
        } else {
          // Compute the difference of the two sets.
          for (var filePath in newPaths) {
            if (!currentPaths.contains(filePath)) {
              collector.startCollectingFor(filePath);
            }
          }
          for (var filePath in currentPaths) {
            if (!newPaths.contains(filePath)) {
              collector.stopCollectingFor(filePath);
            }
          }
        }
      }
    }
    _currentSubscriptions = newSubscriptions;
  }

  /// Returns whether errors should be collected for the file with the given
  /// [path] (because it is being analyzed).
  bool _isIncluded(String path) {
    // TODO(brianwilkerson): Return false if error notifications are globally
    // disabled.
    var isIncluded = false;
    for (var includedPath in _includedPaths) {
      if (_pathContext.isWithin(includedPath, path) ||
          _pathContext.equals(includedPath, path)) {
        isIncluded = true;
        break;
      }
    }
    if (!isIncluded) {
      return false;
    }

    for (var excludedPath in _excludedPaths) {
      if (_pathContext.isWithin(excludedPath, path)) {
        return false;
      }
    }

    return true;
  }

  /// Records a print notification from the analyzer plugin.
  void _recordPrint(plugin.Notification notification) {
    var params = plugin.PluginPrintParams.fromNotification(notification);
    _pluginPrintController.add(params.pluginPrint);
  }

  /// Records a status notification from the analyzer plugin.
  void _setPluginStatus(plugin.Notification notification) {
    var params = plugin.PluginStatusParams.fromNotification(notification);
    var analysis = params.analysis;
    if (analysis == null) {
      return;
    }
    var isAnalyzing = analysis.isAnalyzing;
    _analysisStatusChangesController.add(isAnalyzing);
    pluginStatusAnalyzing = isAnalyzing;
  }
}

class NotificationManager extends AbstractNotificationManager {
  /// The identifier used to identify results from the server.
  static const String serverId = AbstractNotificationManager.serverId;

  /// The channel used to send notifications to the client.
  final ServerCommunicationChannel _channel;

  /// Should be set immediately in [legacy.LegacyAnalysisServer] constructor.
  LegacyAnalysisServer? analysisServer;

  /// Initialize a newly created notification manager.
  new(this._channel, super.pathContext);

  /// Sends errors for a file to the client.
  @override
  void sendAnalysisErrors(String filePath, List<AnalysisError> mergedErrors) {
    if (analysisServer case var analysisServer?) {
      var clientCapabilities = analysisServer.editorClientCapabilities;

      // Check if client prefers LSP diagnostics.
      if (clientCapabilities.publishDiagnostics) {
        var diagnostics = _convertErrorsToLsp(
          analysisServer,
          clientCapabilities,
          mergedErrors,
        );
        var notification = _createLspDiagnosticsNotification(
          filePath,
          diagnostics,
        );

        analysisServer.sendLspNotification(notification);
        return;
      }
    }

    _channel.sendNotification(
      server.AnalysisErrorsParams(
        filePath,
        mergedErrors,
      ).toNotification(clientUriConverter: uriConverter),
    );
  }

  /// Sends folding regions for a file to the client.
  @override
  void sendFoldingRegions(String filePath, List<FoldingRegion> mergedFolding) {
    _channel.sendNotification(
      server.AnalysisFoldingParams(
        filePath,
        mergedFolding,
      ).toNotification(clientUriConverter: uriConverter),
    );
  }

  /// Sends highlight regions for a file to the client.
  @override
  void sendHighlightRegions(
    String filePath,
    List<HighlightRegion> mergedHighlights,
  ) {
    _channel.sendNotification(
      server.AnalysisHighlightsParams(
        filePath,
        mergedHighlights,
      ).toNotification(clientUriConverter: uriConverter),
    );
  }

  /// Sends navigation regions for a file to the client.
  @override
  void sendNavigations(server.AnalysisNavigationParams mergedNavigations) {
    _channel.sendNotification(
      mergedNavigations.toNotification(clientUriConverter: uriConverter),
    );
  }

  /// Sends occurrences for a file to the client.
  @override
  void sendOccurrences(String filePath, List<Occurrences> mergedOccurrences) {
    _channel.sendNotification(
      server.AnalysisOccurrencesParams(
        filePath,
        mergedOccurrences,
      ).toNotification(clientUriConverter: uriConverter),
    );
  }

  /// Sends outlines for a file to the client.
  @override
  void sendOutlines(String filePath, List<Outline> mergedOutlines) {
    _channel.sendNotification(
      server.AnalysisOutlineParams(
        filePath,
        server.FileKind.LIBRARY,
        mergedOutlines[0],
      ).toNotification(clientUriConverter: uriConverter),
    );
  }

  @override
  void sendPluginError(String message) {
    _channel.sendNotification(
      server.ServerPluginErrorParams(message)
          .toNotification(clientUriConverter: uriConverter),
    );
  }

  /// Sends plugin errors to the client.
  @override
  void sendPluginErrorNotification(plugin.Notification notification) {
    var params = plugin.PluginErrorParams.fromNotification(
      notification,
      // No uriConverter here because it's from a plugin.
    );
    // TODO(brianwilkerson): There is no indication for the client as to the
    // fact that the error came from a plugin, let alone which plugin it
    // came from. We should consider whether we really want to send them to
    // the client.
    _channel.sendNotification(
      server.ServerErrorParams(
        params.isFatal,
        params.message,
        params.stackTrace,
      ).toNotification(clientUriConverter: uriConverter),
    );
  }

  List<lsp.Diagnostic> _convertErrorsToLsp(
    LegacyAnalysisServer analysisServer,
    LspClientCapabilities clientCapabilities,
    List<AnalysisError> mergedErrors,
  ) {
    var diagnostics = mergedErrors
        .map(
          (error) => lsp.pluginToDiagnostic(
            analysisServer.uriConverter,
            (path) => analysisServer.getLineInfo(path),
            error,
            supportedTags: clientCapabilities.diagnosticTags,
            clientSupportsCodeDescription:
                clientCapabilities.diagnosticCodeDescription,
            clientSupportsDiagnosticData:
                clientCapabilities.includeAdditionalDiagnosticData,
          ),
        )
        .toList();
    return diagnostics;
  }

  lsp.NotificationMessage _createLspDiagnosticsNotification(
    String filePath,
    List<lsp.Diagnostic> diagnostics,
  ) {
    var params = lsp.PublishDiagnosticsParams(
      uri: uriConverter?.toClientUri(filePath) ?? _pathContext.toUri(filePath),
      diagnostics: diagnostics,
    );
    var notification = lsp.NotificationMessage(
      method: lsp.Method.textDocument_publishDiagnostics,
      params: params,
      jsonrpc: lsp.jsonRpcVersion,
    );
    return notification;
  }
}
