// Copyright (c) 2025, 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_plugin/src/plugin_server.dart';
library;

import 'dart:async';
import 'dart:collection';

import 'package:analysis_server/src/plugin/notification_manager.dart';
import 'package:analysis_server/src/plugin/plugin_manager.dart';
import 'package:analysis_server/src/plugin/server_isolate_channel.dart';
import 'package:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analysis_server/src/session_logger/session_logger.dart';
import 'package:analyzer/dart/analysis/context_root.dart' as analyzer;
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/util/platform_info.dart';
import 'package:analyzer_plugin/channel/channel.dart';
import 'package:analyzer_plugin/protocol/protocol.dart';
import 'package:analyzer_plugin/protocol/protocol_constants.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.dart';
import 'package:analyzer_plugin/src/protocol/protocol_internal.dart';
import 'package:meta/meta.dart';

/// An interface to a configured plugin isolate.
class PluginIsolate {
  /// The maximum size of the [pluginPrints] list.
  ///
  /// After the list grows larger than this size, the first message is dropped,
  /// so that it acts like a ring buffer.
  static const _maxPluginPrintsSize = 1000;

  /// The number of [protocol.PluginPrint]s discarded from [pluginPrints], keyed
  /// to plugin names
  Map<String, int> discardedPluginPrintCount = {};

  /// The path to the root directory of the definition of the plugin on disk
  /// (the directory containing the 'pubspec.yaml' file and the 'bin'
  /// directory).
  final String _path;

  /// The path to the 'plugin.dart' file that will be executed in an isolate, or
  /// `null` if the isolate could not be started.
  final String? executionPath;

  /// The path to the package config file used to control the resolution of
  /// 'package:' URIs, or `null` if the isolate could not be started.
  final String? packageConfigPath;

  /// The object used to manage the receiving and sending of notifications.
  final AbstractNotificationManager _notificationManager;

  /// The instrumentation service that is being used by the analysis server.
  final InstrumentationService _instrumentationService;

  /// The session logger that is to be used by the isolate.
  final SessionLogger sessionLogger;

  /// The context roots that are currently using the results produced by the
  /// plugin.
  final Set<analyzer.ContextRoot> contextRoots = {};

  /// A mapping of each plugin's name to the list of [print] messages which have
  /// been sent by the plugin.
  Map<String, Queue<protocol.PluginPrint>> pluginPrints = {};

  /// The current execution of the plugin, or `null` if the plugin is not
  /// currently being executed.
  PluginSession? currentSession;

  CaughtException? _exception;

  bool isLegacy;

  /// The analysis roots which have been specified by the client. These may be
  /// subdirectories of the context roots.
  AnalysisSetAnalysisRootsParams? _analysisRoots;

  new(
    this._path,
    this.executionPath,
    this.packageConfigPath,
    this._notificationManager,
    this._instrumentationService,
    this.sessionLogger, {
    required this.isLegacy,
  }) {
    // TODO(srawlins): Also print to stdout if this is `dart analyze` or
    // `flutter analyze`.
    _notificationManager.pluginPrints.listen((pluginPrint) {
      var printsForPlugin = pluginPrints.putIfAbsent(
        pluginPrint.pluginName,
        () => ListQueue(),
      );
      if (printsForPlugin.length >= _maxPluginPrintsSize) {
        printsForPlugin.removeFirst();
        discardedPluginPrintCount
          ..putIfAbsent(pluginPrint.pluginName, () => 0)
          ..update(pluginPrint.pluginName, (e) => e++);
      }
      printsForPlugin.add(pluginPrint);
    });
  }

  /// The data known about this plugin, for instrumentation and exception
  /// purposes.
  PluginData get data =>
      PluginData(pluginId, currentSession?._name, currentSession?._version);

  /// The exception that occurred that prevented the plugin from being started,
  /// or `null` if there was no exception (possibly because no attempt has yet
  /// been made to start the plugin).
  CaughtException? get exception => _exception;

  /// The ID of this plugin, used to identify the plugin to users.
  String get pluginId => _path;

  /// Whether this plugin can be started, or `false` if there is a reason that
  /// it cannot be started.
  ///
  /// For example, a plugin cannot be started if there was an error with a
  /// previous attempt to start running it or if the plugin is not correctly
  /// configured.
  bool get _canBeStarted => executionPath != null;

  /// Adds the given [contextRoot] to the set of context roots being analyzed by
  /// this plugin.
  void addContextRoot(analyzer.ContextRoot contextRoot) {
    if (contextRoots.add(contextRoot)) {
      _updatePluginRoots();
    }
  }

  /// Adds the given context [roots] to the set of context roots being analyzed
  /// by this plugin.
  void addContextRoots(Iterable<analyzer.ContextRoot> roots) {
    var changed = false;
    for (var contextRoot in roots) {
      if (contextRoots.add(contextRoot)) {
        changed = true;
      }
    }
    if (changed) {
      _updatePluginRoots();
    }
  }

  /// Whether at least one of the context roots being analyzed contains the file
  /// with the given [filePath].
  bool isAnalyzing(String filePath) {
    for (var contextRoot in contextRoots) {
      if (contextRoot.isAnalyzed(filePath)) {
        return true;
      }
    }
    return false;
  }

  /// Removes the given [contextRoot] from the set of context roots being
  /// analyzed by this plugin.
  void removeContextRoot(analyzer.ContextRoot contextRoot) {
    if (contextRoots.remove(contextRoot)) {
      _updatePluginRoots();
    }
  }

  void reportException(CaughtException exception) {
    // If a previous exception has been reported, do not replace it here; the
    // first should have more "root cause" information.
    _exception ??= exception;
    _instrumentationService.logPluginException(
      data,
      exception.exception,
      exception.stackTrace,
    );
    var message =
        'An error occurred while executing an analyzer plugin: '
        // Sometimes the message is the primary information; sometimes the
        // exception is.
        '${exception.message ?? exception.exception}\n'
        '${exception.stackTrace}';
    _notificationManager.handlePluginError(message);
  }

  /// Requests plugin details from the plugin isolate.
  Future<PluginDetailsResult?> requestDetails() async {
    if (currentSession case PluginSession currentSession) {
      Response response;
      try {
        response = await currentSession
            .sendRequest(PluginDetailsParams())
            .timeout(const Duration(seconds: 5));
      } on TimeoutException {
        // TODO(srawlins): Return a `PluginDetailsResult` with a specific error?
        return null;
      }
      if (response.error != null) throw response.error!;
      return PluginDetailsResult.fromResponse(response);
    } else {
      return null;
    }
  }

  /// If the plugin is currently running, sends a request based on the given
  /// [params] to the plugin.
  ///
  /// If the plugin is not running, the request will silently be dropped.
  void sendRequest(RequestParams params) {
    currentSession?.sendRequest(params);
  }

  /// Sets the analysis roots, which may be subdirectories of the context roots.
  void setAnalysisRoots(AnalysisSetAnalysisRootsParams params) {
    _analysisRoots = params;
    if (contextRoots.isNotEmpty) {
      _updatePluginRoots();
    }
  }

  /// Starts a new isolate that is running the plugin.
  ///
  /// Returns the [PluginSession] used to interact with the plugin, or `null` if
  /// the plugin could not be run.
  Future<PluginSession?> start(String? byteStorePath, String sdkPath) async {
    if (currentSession != null) {
      throw StateError('Cannot start a plugin that is already running.');
    }
    currentSession = PluginSession(this);
    var isRunning = await currentSession!.start(byteStorePath, sdkPath);
    if (!isRunning) {
      currentSession = null;
    }
    return currentSession;
  }

  /// Requests that the plugin shut down.
  Future<void> stop() {
    if (currentSession == null) {
      if (_exception != null) {
        // Plugin crashed, nothing to do.
        return Future<void>.value();
      }
      throw StateError('Cannot stop a plugin that is not running.');
    }
    var doneFuture = currentSession!.stop();
    currentSession = null;
    return doneFuture;
  }

  /// Computes the effective analysis roots for this plugin by intersecting
  /// any client-specified [_analysisRoots] with [contextRoots].
  AnalysisSetAnalysisRootsParams _computeEffectiveAnalysisRoots() {
    var analysisRoots = _analysisRoots;
    if (analysisRoots == null) {
      return AnalysisSetAnalysisRootsParams([
        for (var contextRoot in contextRoots) contextRoot.root.path,
      ], const []);
    }

    var effectiveIncluded = <String>{};
    var effectiveExcluded = <String>{};

    for (var contextRoot in contextRoots) {
      var pathContext = contextRoot.resourceProvider.pathContext;
      var contextPath = contextRoot.root.path;

      // Skip if the context root is completely excluded by client excluded
      // paths.
      var isContextExcluded = analysisRoots.excluded.any(
        (e) => pathContext.isWithin(e, contextPath) || e == contextPath,
      );
      if (isContextExcluded) continue;

      // Check if any client included path contains this context root.
      var isContextCovered = analysisRoots.included.any(
        (i) => pathContext.isWithin(i, contextPath) || i == contextPath,
      );
      if (isContextCovered) {
        effectiveIncluded.add(contextPath);
      } else {
        // Check for subpaths within this context root.
        for (var clientIncluded in analysisRoots.included) {
          if (pathContext.isWithin(contextPath, clientIncluded)) {
            effectiveIncluded.add(clientIncluded);
          }
        }
      }

      // Add client exclusions that fall inside this context root.
      for (var clientExcluded in analysisRoots.excluded) {
        if (pathContext.isWithin(contextPath, clientExcluded)) {
          effectiveExcluded.add(clientExcluded);
        }
      }
      effectiveExcluded.addAll(contextRoot.excludedPaths);
    }

    return AnalysisSetAnalysisRootsParams(
      effectiveIncluded.toList(),
      effectiveExcluded.toList(),
    );
  }

  /// Creates and returns the channel used to communicate with the server.
  ServerCommunicationChannel _createChannel() {
    return ServerIsolateChannel(
      Uri.file(executionPath!, windows: platform.isWindows),
      Uri.file(packageConfigPath!, windows: platform.isWindows),
      _instrumentationService,
      sessionLogger,
    );
  }

  /// Updates the context roots that the plugin should be analyzing.
  void _updatePluginRoots() {
    sendRequest(
      AnalysisSetContextRootsParams(
        contextRoots
            .map(
              (contextRoot) => ContextRoot(
                contextRoot.root.path,
                contextRoot.excludedPaths.toList(),
                optionsFile: contextRoot.optionsFile?.path,
              ),
            )
            .toList(),
      ),
    );

    // If analysis roots have been set by the client, send an
    // `analysis.setAnalysisRoots` request to the plugin containing the
    // intersection of the client analysis roots and this plugin's context
    // roots. But if not, go ahead and send this request using the context
    // roots. Plugin isolates running on the analysis_server_plugin version
    // >= 0.3.16 only respect the `analysis.setAnalysisRoots` request, and not
    // the `analysis.setContextRoots` request.
    var analysisRoots = _computeEffectiveAnalysisRoots();
    sendRequest(analysisRoots);
  }
}

/// Information about the execution of a single plugin.
@visibleForTesting
class PluginSession {
  /// The maximum number of milliseconds that server should wait for a response
  /// from a plugin before deciding that the plugin is hung.
  static const Duration _maximumResponseTime = Duration(minutes: 2);

  /// The length of time to wait after sending a 'plugin.shutdown' request
  /// before a failure to terminate will cause the isolate to be killed.
  static const Duration _waitForShutdownDuration = Duration(seconds: 10);

  /// The information about the plugin being executed.
  final PluginIsolate _isolate;

  /// The completer used to signal when the plugin has stopped.
  final Completer<void> pluginStoppedCompleter = Completer<void>();

  /// The channel used to communicate with the plugin.
  ServerCommunicationChannel? channel;

  /// The index of the next request to be sent to the plugin.
  @visibleForTesting
  int requestId = 0;

  /// A table mapping the id's of requests to the functions used to handle the
  /// response to those requests.
  @visibleForTesting
  final pendingRequests = <String, _PendingRequest>{};

  /// A boolean indicating whether the plugin is compatible with the version of
  /// the plugin API being used by this server.
  bool isCompatible = true;

  /// The glob patterns of files that the plugin is interested in knowing about.
  List<String>? interestingFileGlobs;

  /// The name to be used when reporting problems related to the plugin.
  String? _name;

  /// The version number to be used when reporting problems related to the
  /// plugin.
  String? _version;

  new(this._isolate);

  /// The next request ID, encoded as a string.
  ///
  /// This increments the ID so that a different result will be returned on each
  /// invocation.
  String get nextRequestId => (requestId++).toString();

  /// A future that will complete when the plugin has stopped.
  Future<void> get onDone => pluginStoppedCompleter.future;

  /// Handles the given [notification] from [PluginServer].
  void handleNotification(Notification notification) {
    if (notification.event == PLUGIN_NOTIFICATION_ERROR) {
      var params = PluginErrorParams.fromNotification(notification);
      if (params.isFatal) {
        _isolate.stop();
        stop();
      }
    }
    _isolate._notificationManager.handlePluginNotification(
      _isolate.pluginId,
      notification,
    );
  }

  /// Handles the fact that the plugin has stopped.
  void handleOnDone() {
    if (channel != null) {
      channel!.close();
      channel = null;
    }
    pluginStoppedCompleter.complete(null);
  }

  /// Handles the fact that an unhandled error has occurred in the plugin.
  void handleOnError(Object? error) {
    if (error case [String message, String stackTraceString]) {
      var stackTrace = StackTrace.fromString(stackTraceString);
      var exception = PluginException(message);
      _isolate.reportException(
        CaughtException.withMessage(message, exception, stackTrace),
      );
    } else {
      throw ArgumentError.value(
        error,
        'error',
        'expected to be a two-element List of Strings.',
      );
    }
  }

  /// Handles a [response] from the plugin by completing the future that was
  /// created when the request was sent.
  void handleResponse(Response response) {
    var requestData = pendingRequests.remove(response.id);
    if (requestData != null) {
      var responseTime = DateTime.now().millisecondsSinceEpoch;
      var duration = responseTime - requestData.requestTime;
      PluginManager.recordResponseTime(_isolate, requestData.method, duration);
      var completer = requestData.completer;
      completer.complete(response);
    }
  }

  /// Whether there are any requests that have not been responded to within the
  /// maximum allowed amount of time.
  bool isNonResponsive() {
    // TODO(brianwilkerson): Figure out when to invoke this method in order to
    // identify non-responsive plugins and kill them.
    var cutOffTime =
        DateTime.now().millisecondsSinceEpoch -
        _maximumResponseTime.inMilliseconds;
    for (var requestData in pendingRequests.values) {
      if (requestData.requestTime < cutOffTime) {
        return true;
      }
    }
    return false;
  }

  /// Sends a request, based on the given [parameters].
  ///
  /// Returns a future that will complete when a response is received.
  Future<Response> sendRequest(RequestParams parameters) {
    var channel = this.channel;
    if (channel == null) {
      throw StateError('Cannot send a request to a plugin that has stopped.');
    }
    var id = nextRequestId;
    var completer = Completer<Response>();
    var requestTime = DateTime.now().millisecondsSinceEpoch;
    var request = parameters.toRequest(id);
    pendingRequests[id] = _PendingRequest(
      request.method,
      requestTime,
      completer,
    );
    channel.sendRequest(request);
    completer.future.then((response) {
      // If a RequestError is returned in the response, report this as an
      // exception.
      if (response.error case var error?) {
        if (error.code == RequestErrorCode.UNKNOWN_REQUEST) {
          // The plugin doesn't support this request. It may just be using an
          // older version of the `analysis_server_plugin` package.
          _isolate._instrumentationService.logInfo(
            "Plugin cannot handle request '${request.method}' with parameters: "
            '$parameters.',
          );
          _isolate.sessionLogger.logInfo(
            "Plugin cannot handle request '${request.method}' with parameters: "
            '$parameters.',
          );
          return;
        }
        var stackTrace = StackTrace.fromString(error.stackTrace!);
        var exception = PluginException(error.message);
        _isolate.reportException(
          CaughtException.withMessage(error.message, exception, stackTrace),
        );
      }
    });
    return completer.future;
  }

  /// Starts a new isolate that is running this plugin.
  ///
  /// The plugin will be sent the given [byteStorePath]. Returns whether the
  /// plugin is compatible and running.
  Future<bool> start(String? byteStorePath, String sdkPath) async {
    if (channel != null) {
      throw StateError('Cannot start a plugin that is already running.');
    }
    if (byteStorePath == null || byteStorePath.isEmpty) {
      throw StateError('Missing byte store path');
    }
    if (!isCompatible) {
      _isolate.reportException(
        CaughtException(
          PluginException('Plugin is not compatible.'),
          StackTrace.current,
        ),
      );
      return false;
    }
    if (!_isolate._canBeStarted) {
      _isolate.reportException(
        CaughtException(
          PluginException('Plugin cannot be started.'),
          StackTrace.current,
        ),
      );
      return false;
    }
    channel = _isolate._createChannel();
    // TODO(brianwilkerson): Determine if await is necessary, if so, change the
    // return type of `channel.listen` to `Future<void>`.
    await (channel!.listen(
      handleResponse,
      handleNotification,
      onDone: handleOnDone,
      onError: handleOnError,
    ) as dynamic);
    if (channel == null) {
      // If there is an error when starting the isolate, the channel will invoke
      // `handleOnDone`, which will cause `channel` to be set to `null`.
      _isolate.reportException(
        CaughtException(
          PluginException('Unrecorded error while starting the plugin.'),
          StackTrace.current,
        ),
      );
      return false;
    }
    var response = await sendRequest(
      PluginVersionCheckParams(byteStorePath, sdkPath, '1.0.0-alpha.0'),
    );
    var result = PluginVersionCheckResult.fromResponse(response);
    isCompatible = result.isCompatible;
    interestingFileGlobs = result.interestingFiles;
    _name = result.name;
    _version = result.version;
    if (!isCompatible) {
      unawaited(sendRequest(PluginShutdownParams()));
      _isolate.reportException(
        CaughtException(
          PluginException('Plugin is not compatible.'),
          StackTrace.current,
        ),
      );
      return false;
    }
    return true;
  }

  /// Requests that the plugin shutdown.
  Future<void> stop() {
    if (channel == null) {
      throw StateError('Cannot stop a plugin that is not running.');
    }
    sendRequest(PluginShutdownParams());
    Future.delayed(_waitForShutdownDuration, () {
      if (channel != null) {
        channel?.kill();
        channel = null;
      }
    });
    return pluginStoppedCompleter.future;
  }
}

/// Information about a request that has been sent but for which a response has
/// not yet been received.
class _PendingRequest {
  /// The method of the request.
  final String method;

  /// The time at which the request was sent to the plugin.
  final int requestTime;

  /// The completer that will be used to complete the future when the response
  /// is received from the plugin.
  final Completer<Response> completer;

  /// Initialize a pending request.
  new(this.method, this.requestTime, this.completer);
}
