// Copyright (c) 2021, 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:dds/src/dap/logging.dart';
import 'package:dds/src/dap/protocol_generated.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';

import 'test_client.dart';
import 'test_server.dart';

/// A [RegExp] that matches the "Connecting to VM Service" banner that is sent
/// by the DAP adapter as the first output event for a debug session.
final dapVmServiceBannerPattern =
    RegExp(r'Connecting to VM Service at ([^\s]+)\s');

/// Whether to run the DAP server in-process with the tests, or externally in
/// another process.
///
/// By default tests will run the DAP server out-of-process to match the real
/// use from editors, but this complicates debugging the adapter. Set this env
/// variables to run the server in-process for easier debugging (this can be
/// simplified in VS Code by using a launch config with custom CodeLens links).
final useInProcessDap = Platform.environment['DAP_TEST_INTERNAL'] == 'true';

/// Whether to print all protocol traffic to stdout while running tests.
///
/// This is useful for debugging locally or on the bots and will include both
/// DAP traffic (between the test DAP client and the DAP server) and the VM
/// Service traffic (wrapped in a custom 'dart.log' event).
///
/// Verbose logging is temporarily enabled for all test runs to try and
/// understand failures noted at https://github.com/dart-lang/sdk/issues/48274.
/// Once resolved, this variable can be set back to the result of:
///     Platform.environment['DAP_TEST_VERBOSE'] == 'true'
final verboseLogging = true;

/// A [RegExp] that matches the `path` part of a VM Service URI that contains
/// an authentication token.
final vmServiceAuthCodePathPattern = RegExp(r'^/[\w_\-=]{5,15}/ws$');

/// A [RegExp] that matches the "Observatory listening on" banner that is sent
/// by the VM when not using --write-service-info.
final vmServiceBannerPattern = RegExp(r'Observatory listening on ([^\s]+)\s');

/// The root of the SDK containing the current running VM.
final sdkRoot = path.dirname(path.dirname(Platform.resolvedExecutable));

/// Expects the lines in [actual] to match the relevant matcher in [expected],
/// ignoring differences in line endings and trailing whitespace.
void expectLines(String actual, List<Object> expected) {
  expect(
    actual.replaceAll('\r\n', '\n').trim().split('\n'),
    equals(expected),
  );
}

/// Expects [actual] starts with [expected], ignoring differences in line
/// endings and trailing whitespace.
void expectLinesStartWith(String actual, List<String> expected) {
  expect(
    actual.replaceAll('\r\n', '\n').trim(),
    startsWith(expected.join('\n').trim()),
  );
}

/// Expects [response] to fail with a `message` matching [messageMatcher].
expectResponseError<T>(Future<T> response, Matcher messageMatcher) {
  expect(
    response,
    throwsA(
      const TypeMatcher<Response>()
          .having((r) => r.success, 'success', isFalse)
          .having((r) => r.message, 'message', messageMatcher),
    ),
  );
}

/// Returns the 1-base line in [file] that contains [searchText].
int lineWith(File file, String searchText) =>
    file.readAsLinesSync().indexWhere((line) => line.contains(searchText)) + 1;

Future<Process> startDartProcessPaused(
  String script,
  List<String> args, {
  required String cwd,
  List<String>? vmArgs,
}) async {
  final vmPath = Platform.resolvedExecutable;
  vmArgs ??= [];
  vmArgs.addAll([
    '--enable-vm-service=0',
    '--pause_isolates_on_start',
  ]);
  final processArgs = [
    ...vmArgs,
    script,
    ...args,
  ];

  return Process.start(
    vmPath,
    processArgs,
    workingDirectory: cwd,
  );
}

/// Monitors [process] for the Observatory/VM Service banner and extracts the
/// VM Service URI.
Future<Uri> waitForStdoutVmServiceBanner(Process process) {
  final _vmServiceUriCompleter = Completer<Uri>();

  late StreamSubscription<String> vmServiceBannerSub;
  vmServiceBannerSub = process.stdout.transform(utf8.decoder).listen(
    (line) {
      final match = vmServiceBannerPattern.firstMatch(line);
      if (match != null) {
        _vmServiceUriCompleter.complete(Uri.parse(match.group(1)!));
        vmServiceBannerSub.cancel();
      }
    },
    onDone: () {
      if (!_vmServiceUriCompleter.isCompleted) {
        _vmServiceUriCompleter.completeError('Stream ended');
      }
    },
  );

  return _vmServiceUriCompleter.future;
}

/// A helper class containing the DAP server/client for DAP integration tests.
class DapTestSession {
  DapTestServer server;
  DapTestClient client;
  final Directory testDir =
      Directory.systemTemp.createTempSync('dart-sdk-dap-test');
  late final Directory testAppDir;
  late final Directory testPackagesDir;

  DapTestSession._(this.server, this.client) {
    testAppDir = testDir.createTempSync('app');
    createPubspec(testAppDir, 'my_test_project');
    testPackagesDir = testDir.createTempSync('packages');
  }

  /// Adds package with [name] (optionally at [packageFolderUri]) to the
  /// project in [dir].
  ///
  /// If [packageFolderUri] is not supplied, will use [Isolate.resolvePackageUri]
  /// assuming the package is available to the tests.
  Future<void> addPackageDependency(
    Directory dir,
    String name, [
    Uri? packageFolderUri,
  ]) async {
    final proc = await Process.run(
      Platform.resolvedExecutable,
      [
        'pub',
        'add',
        name,
        if (packageFolderUri != null) ...[
          '--path',
          packageFolderUri.toFilePath(),
        ],
      ],
      workingDirectory: dir.path,
    );
    expect(
      proc.exitCode,
      isZero,
      reason: '${proc.stdout}\n${proc.stderr}'.trim(),
    );
  }

  /// Create a simple package named `foo` that has an empty `foo` function.
  Future<Uri> createFooPackage() {
    return createSimplePackage(
      'foo',
      '''
foo() {
  // Does nothing.
}
      ''',
    );
  }

  void createPubspec(Directory dir, String projectName) {
    final pubspecFile = File(path.join(dir.path, 'pubspec.yaml'));
    pubspecFile
      ..createSync()
      ..writeAsStringSync('''
name: $projectName
version: 1.0.0

environment:
  sdk: '>=2.13.0 <3.0.0'
''');
  }

  /// Creates a simple package script and adds the package to
  /// .dart_tool/package_config.json
  Future<Uri> createSimplePackage(
    String name,
    String content,
  ) async {
    final packageDir = Directory(path.join(testPackagesDir.path, name))
      ..createSync(recursive: true);
    final packageLibDir = Directory(path.join(packageDir.path, 'lib'))
      ..createSync(recursive: true);

    // Create a pubspec and a implementation file in the lib folder.
    createPubspec(packageDir, name);
    final testFile = File(path.join(packageLibDir.path, '$name.dart'));
    testFile.writeAsStringSync(content);

    // Add this new package as a dependency for the app.
    final fileUri = Uri.file('${packageDir.path}/');
    await addPackageDependency(testAppDir, name, fileUri);

    return Uri.parse('package:$name/$name.dart');
  }

  /// Creates a file in a temporary folder to be used as an application for testing.
  ///
  /// The file will be deleted at the end of the test run.
  File createTestFile(String content) {
    final testFile = File(path.join(testAppDir.path, 'test_file.dart'));
    testFile.writeAsStringSync(content);
    return testFile;
  }

  Future<void> tearDown() async {
    await client.stop();
    await server.stop();

    // Clean up any temp folders created during the test runs.
    await tryDelete(testDir);
  }

  /// Tries to delete [dir] multiple times before printing a warning and giving up.
  ///
  /// This avoids "The process cannot access the file because it is being
  /// used by another process" errors on Windows trying to delete folders that
  /// have only very recently been unlocked.
  Future<void> tryDelete(Directory dir) async {
    const maxAttempts = 10;
    const delay = Duration(milliseconds: 100);
    var attempt = 0;
    while (++attempt <= maxAttempts) {
      try {
        testDir.deleteSync(recursive: true);
        break;
      } catch (e) {
        if (attempt == maxAttempts) {
          print('Failed to delete $testDir after $maxAttempts attempts.\n$e');
          break;
        }
        await Future.delayed(delay);
      }
    }
  }

  static Future<DapTestSession> setUp({List<String>? additionalArgs}) async {
    final server = await _startServer(additionalArgs: additionalArgs);
    final client = await DapTestClient.connect(
      server,
      captureVmServiceTraffic: verboseLogging,
      logger: verboseLogging ? print : null,
    );
    return DapTestSession._(server, client);
  }

  /// Starts a DAP server that can be shared across tests.
  static Future<DapTestServer> _startServer({
    Logger? logger,
    List<String>? additionalArgs,
  }) async {
    return useInProcessDap
        ? await InProcessDapTestServer.create(
            logger: logger,
            additionalArgs: additionalArgs,
          )
        : await OutOfProcessDapTestServer.create(
            logger: logger,
            additionalArgs: additionalArgs,
          );
  }
}
