// 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();
  }

  /// 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);
}
