// 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_generated.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');

    // Prevent flow analysis from marking code below as being dead.
    const useSnapshot = 1 > 0;
    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();
  }
}
