// Copyright (c) 2019, 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:io';

import 'package:analysis_server/lsp_protocol/protocol.dart';
import 'package:analysis_server/src/lsp/channel/lsp_byte_stream_channel.dart';
import 'package:analysis_server/src/services/pub/pub_command.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart';

import '../../lsp/server_abstract.dart';

abstract class AbstractLspAnalysisServerIntegrationTest
    with ClientCapabilitiesHelperMixin, LspAnalysisServerTestMixin {
  final List<String> vmArgs = [];
  LspServerClient? client;
  InstrumentationService? instrumentationService;
  final Map<num, Completer<ResponseMessage>> _completers = {};
  String dartSdkPath = dirname(dirname(Platform.resolvedExecutable));

  LspByteStreamServerChannel get channel => client!.channel!;

  @override
  Stream<Message> get serverToClient => client!.serverToClient;

  /// Sends a request to the server and unwraps the result. Throws if the
  /// response was not successful or returned an error.
  @override
  Future<T> expectSuccessfulResponseTo<T, R>(
      RequestMessage request, T Function(R) fromJson) async {
    final resp = await sendRequestToServer(request);
    final error = resp.error;
    if (error != null) {
      throw error;
    } else if (T == Null) {
      return resp.result == null
          ? null as T
          : throw 'Expected Null response but got ${resp.result}';
    } else {
      return fromJson(resp.result as R);
    }
  }

  void newFile(String path, String content) =>
      File(path).writeAsStringSync(content);

  void newFolder(String path) => Directory(path).createSync(recursive: true);

  @override
  void sendNotificationToServer(NotificationMessage notification) =>
      channel.sendNotification(notification);

  @override
  Future<ResponseMessage> sendRequestToServer(RequestMessage request) {
    final completer = Completer<ResponseMessage>();
    final id = request.id.map((number) => number,
        (string) => throw 'String IDs not supported in tests');
    _completers[id] = completer;

    channel.sendRequest(request);

    return completer.future;
  }

  @override
  void sendResponseToServer(ResponseMessage response) =>
      channel.sendResponse(response);

  @mustCallSuper
  Future<void> setUp() async {
    // Set up temporary folder for the test.
    projectFolderPath = Directory.systemTemp
        .createTempSync('analysisServer')
        .resolveSymbolicLinksSync();
    newFolder(projectFolderPath);
    newFolder(join(projectFolderPath, 'lib'));
    projectFolderUri = Uri.file(projectFolderPath);
    mainFilePath = join(projectFolderPath, 'lib', 'main.dart');
    mainFileUri = Uri.file(mainFilePath);
    analysisOptionsPath = join(projectFolderPath, 'analysis_options.yaml');
    analysisOptionsUri = Uri.file(analysisOptionsPath);

    final client = LspServerClient(instrumentationService);
    this.client = client;
    await client.start(dartSdkPath: dartSdkPath, vmArgs: vmArgs);
    client.serverToClient.listen((message) {
      if (message is ResponseMessage) {
        final id = message.id!.map((number) => number,
            (string) => throw 'String IDs not supported in tests');

        final completer = _completers[id];
        if (completer == null) {
          throw 'Response with ID $id was unexpected';
        } else {
          _completers.remove(id);
          completer.complete(message);
        }
      }
    });
  }

  void tearDown() {
    // TODO(dantup): Graceful shutdown?
    client?.close();
  }
}

class LspServerClient {
  final InstrumentationService? instrumentationService;
  Process? _process;
  LspByteStreamServerChannel? channel;
  final StreamController<Message> _serverToClient =
      StreamController<Message>.broadcast();

  LspServerClient(this.instrumentationService);

  Future<int> get exitCode => _process!.exitCode;

  Stream<Message> get serverToClient => _serverToClient.stream;

  void close() {
    channel?.close();
    _process?.kill();
  }

  /// Find the root directory of the analysis_server package by proceeding
  /// upward to the 'test' dir, and then going up one more directory.
  String findRoot(String pathname) {
    while (!['benchmark', 'test'].contains(basename(pathname))) {
      var parent = dirname(pathname);
      if (parent.length >= pathname.length) {
        throw Exception("Can't find root directory");
      }
      pathname = parent;
    }
    return dirname(pathname);
  }

  Future start({
    required String dartSdkPath,
    List<String>? vmArgs,
  }) async {
    if (_process != null) {
      throw Exception('Process already started');
    }

    var dartBinary = join(dartSdkPath, 'bin', 'dart');

    // Setting the `TEST_SERVER_SNAPSHOT` env var to 'false' will disable the
    // snapshot and run from source.
    var useSnapshot = Platform.environment['TEST_SERVER_SNAPSHOT'] != 'false';
    String serverPath;

    if (useSnapshot) {
      serverPath = normalize(join(
          dartSdkPath, 'bin', 'snapshots', 'analysis_server.dart.snapshot'));
    } else {
      final rootDir =
          findRoot(Platform.script.toFilePath(windows: Platform.isWindows));
      serverPath = normalize(join(rootDir, 'bin', 'server.dart'));
    }

    final arguments = [...?vmArgs, serverPath, '--lsp', '--suppress-analytics'];
    final process = await Process.start(
      dartBinary,
      arguments,
      environment: {PubCommand.disablePubCommandEnvironmentKey: 'true'},
    );
    _process = process;
    process.exitCode.then((int code) {
      if (code != 0) {
        // TODO(dantup): Log/fail tests...
      }
    });

    // If the server writes to stderr, fail tests with a more useful message
    // (rather than having the test just hang waiting for a response).
    process.stderr.listen((data) {
      final message = String.fromCharCodes(data);
      throw 'Analysis Server wrote to stderr:\n\n$message';
    });

    channel = LspByteStreamServerChannel(process.stdout, process.stdin,
        instrumentationService ?? InstrumentationService.NULL_SERVICE)
      ..listen(_serverToClient.add);
  }
}

/// An [InstrumentationLogger] that buffers logs until [debugStdio()] is called.
class PrintableLogger extends InstrumentationLogger {
  bool _printLogs = false;
  final _buffer = StringBuffer();

  void debugStdio() {
    print(_buffer.toString());
    _buffer.clear();
    _printLogs = true;
  }

  @override
  void log(String message) {
    if (_printLogs) {
      print(message);
    } else {
      _buffer.writeln(message);
    }
  }

  @override
  Future<void> shutdown() async {
    _printLogs = false;
    _buffer.clear();
  }
}
