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

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

import 'package:analysis_server/lsp_protocol/protocol.dart' show jsonRpcVersion;
import 'package:analysis_server/src/lsp/lsp_packet_transformer.dart';
import 'package:analysis_server/src/server/driver.dart';
import 'package:analysis_server/src/session_logger/log_entry.dart';

/// The driver used to communicate with the analysis server.
class ServerDriver {
  /// The protocol being used by the server.
  final ServerProtocol _protocol;

  /// A list of arguments from the command-line used to start the server.
  final List<String> arguments;

  /// The sink used to send messages from the IDE to the server's stdin, or
  /// `null` if the server has not been started using [start].
  IOSink? _stdinSink;

  /// The socket used to send messages from DTD to the server, or `null` if the
  /// server has not been connected to DTD using [connectToDtd].
  WebSocket? _dtdSocket;

  /// Stream controller for analysis server output messages.
  final StreamController<Message> _serverMessagesController =
      StreamController();

  /// Creates a new driver that can be used to communicate with a server.
  ///
  /// When the server is [start]ed, it will use the given [protocol].
  ///
  /// The server is run in a separate process.
  // TODO(brianwilkerson): Add a flag controlling whether the server is in the
  //  same process as the driver or in a separate process.
  factory ServerDriver({required List<String> arguments}) {
    var parsedArgs = Driver.createArgParser().parse(arguments);

    var protocolOption = parsedArgs.option(Driver.serverProtocolOption);
    var protocol = switch (protocolOption) {
      Driver.protocolAnalyzer => ServerProtocol.legacy,
      Driver.protocolLsp => ServerProtocol.lsp,
      null => throw StateError('No protocol specified'),
      _ => throw StateError('Unrecognized protocol $protocolOption'),
    };

    var useFineDependencies = parsedArgs.wasParsed(
      Driver.withFineDependenciesOption,
    );

    return ServerDriver._(
      arguments: [
        '--${Driver.serverProtocolOption}=${protocol.flagValue}',
        if (useFineDependencies) '--${Driver.withFineDependenciesOption}',
      ],
      protocol: protocol,
    );
  }

  /// Creates a new driver that can be used to communicate with a server.
  ///
  /// When the server is [start]ed, it will use the given [_protocol].
  ///
  /// The server is run in a separate process.
  ServerDriver._({required this.arguments, required this._protocol});

  /// The messages read from the analysis server's stdout.
  Stream<Message> get serverMessages => _serverMessagesController.stream;

  /// Returns the path to the `dart` executable.
  String get _dartExecutable {
    return Platform.resolvedExecutable;
  }

  /// Create a websocket through which DTD messages can be sent to the server
  /// and send a request to the server asking it to connect to the socket.
  // ignore: unnecessary_async
  Future<void> connectToDtd() async {
    // TODO(brianwilkerson): Implement this.
    throw UnimplementedError();
    // var socketUri = 'ws://';
    // _dtdSocket = await WebSocket.connect(socketUri);
  }

  /// Send an exit request to the server, then close the communication channels
  /// used to communicate with the server.
  void exit() {
    if (_protocol == ServerProtocol.lsp) {
      sendMessageFromIde(
        Message({
          'id': 0,
          'method': 'exit',
          'jsonrpc': jsonRpcVersion,
          'clientRequestTime': DateTime.now().millisecondsSinceEpoch,
        }),
      );
    }
    _stdinSink?.close();
    _stdinSink = null;
    _dtdSocket?.close();
    _dtdSocket = null;
    _serverMessagesController.close();
  }

  void sendMessageFromDTD(Message message) {
    if (_dtdSocket case var socket?) {
      socket.add(json.encode(message));
    } else {
      throw StateError(
        "The method 'connectToDtd' must be invoked before "
        'messages can be sent from DTD.',
      );
    }
  }

  void sendMessageFromFileWatcher(Message message) {
    // TODO(brianwilkerson): Implementing this will require some additional
    //  support in the server. The most likely approach is to add support for a
    //  new protocol that will fake receiving a watch event.
  }

  /// Send the given [message] to the server using the communication channel
  /// used by the IDE.
  void sendMessageFromIde(Message message) {
    if (_stdinSink case IOSink writeSink) {
      var jsonEncodedBody = jsonEncode(message);
      if (_protocol == ServerProtocol.lsp) {
        var utf8EncodedBody = utf8.encode(jsonEncodedBody);
        var header =
            'Content-Length: ${utf8EncodedBody.length}\r\n'
            'Content-Type: application/vscode-jsonrpc; charset=utf-8\r\n\r\n';
        var asciiEncodedHeader = ascii.encode(header);

        // Header is always ascii, body is always utf8!
        writeSink.add(asciiEncodedHeader);
        writeSink.add(utf8EncodedBody);
      } else {
        writeSink.write(jsonEncodedBody);
      }
    } else {
      throw StateError(
        "The method 'start' must be invoked before "
        'messages can be sent from the IDE.',
      );
    }
  }

  void sendMessageFromPluginIsolate(Message message) {
    // TODO(brianwilkerson): Implementing this will require some additional
    //  support in the server. Two possibilities to consider:
    //  1. Add a protocol to fake receiving a messsage from the plugin isolate.
    //  2. Add a protocol to connect to a web socket as if it were a connection
    //     to a plugin isolate.
    //  The first is likely to be the easier path forward.
  }

  /// Send a shutdown request to the server.
  void shutdown() {
    if (_protocol == ServerProtocol.legacy) {
      sendMessageFromIde(
        Message({
          'id': 0,
          'method': 'server.shutdown',
          'clientRequestTime': DateTime.now().millisecondsSinceEpoch,
        }),
      );
    } else if (_protocol == ServerProtocol.lsp) {
      sendMessageFromIde(
        Message({
          'id': 0,
          'method': 'shutdown',
          'jsonrpc': jsonRpcVersion,
          'clientRequestTime': DateTime.now().millisecondsSinceEpoch,
        }),
      );
    }
  }

  /// Create and start the server.
  Future<void> start() async {
    if (_stdinSink != null) {
      throw StateError(
        'Analysis server already started, only one active instance is allowed '
        'at a time.',
      );
    }
    var process = await Process.start(_dartExecutable, [
      'language-server',
      '--suppress-analytics',
      ...arguments,
    ]);
    _stdinSink = process.stdin;
    if (_protocol == ServerProtocol.lsp) {
      process.stdout
          .transform(LspPacketTransformer())
          .listen(_receiveMessageFromServer);
    } else {
      process.stdout
          .transform(const Utf8Decoder())
          .transform(const LineSplitter())
          .listen(_receiveMessageFromServer);
    }
  }

  void _receiveMessageFromServer(String message) {
    if (_serverMessagesController.isClosed) {
      stderr.writeln('Got analysis server message after shutdown:\n$message');
    } else {
      _serverMessagesController.add(jsonDecode(message) as Message);
    }
  }
}

/// An indication of the protocol to be used when communicating with the server.
enum ServerProtocol {
  legacy('analyzer'),
  lsp('lsp');

  final String flagValue;
  const ServerProtocol(this.flagValue);
}
