// Copyright 2013 The Flutter Authors. 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 'dart:isolate';
import 'dart:math';

import 'package:async/async.dart';
import 'package:http_multi_server/http_multi_server.dart';
import 'package:image/image.dart';
import 'package:package_config/package_config.dart';
import 'package:path/path.dart' as p;
import 'package:pool/pool.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_packages_handler/shelf_packages_handler.dart';
import 'package:shelf_static/shelf_static.dart';
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:skia_gold_client/skia_gold_client.dart';
import 'package:stream_channel/stream_channel.dart';

import 'package:test_api/src/backend/runtime.dart';
import 'package:test_api/src/backend/suite_platform.dart';
import 'package:test_core/src/runner/configuration.dart';
import 'package:test_core/src/runner/environment.dart';
import 'package:test_core/src/runner/platform.dart';
import 'package:test_core/src/runner/plugin/platform_helpers.dart';
import 'package:test_core/src/runner/runner_suite.dart';
import 'package:test_core/src/runner/suite.dart';
import 'package:test_core/src/util/io.dart';
import 'package:test_core/src/util/stack_trace_mapper.dart';

import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:web_test_utils/image_compare.dart';

import 'browser.dart';
import 'environment.dart' as env;
import 'utils.dart';

const Map<String, String> coopCoepHeaders = <String, String>{
  'Cross-Origin-Opener-Policy': 'same-origin',
  'Cross-Origin-Embedder-Policy': 'require-corp',
};

/// Custom test platform that serves web engine unit tests.
class BrowserPlatform extends PlatformPlugin {
  BrowserPlatform._({
    required this.browserEnvironment,
    required this.server,
    required this.renderer,
    required this.isDebug,
    required this.isWasm,
    required this.doUpdateScreenshotGoldens,
    required this.packageConfig,
    required this.skiaClient,
    required this.overridePathToCanvasKit,
  }) {
    // The cascade of request handlers.
    final shelf.Cascade cascade = shelf.Cascade()
        // The web socket that carries the test channels for running tests and
        // reporting restuls. See [_browserManagerFor] and [BrowserManager.start]
        // for details on how the channels are established.
        .add(_webSocketHandler.handler)

        // Serves /packages/* requests; fetches files and sources from
        // pubspec dependencies.
        //
        // Includes:
        //  * Requests for Dart sources from source maps
        //  * Assets that are part of the engine sources, such as Ahem.ttf
        .add(_packageUrlHandler)
        .add(_canvasKitOverrideHandler)

        // Serves files from the out/web_tests/ directory at the root (/) URL path.
        .add(buildDirectoryHandler)
        .add(_testImageListingHandler)

        // Serves the initial HTML for the test.
        .add(_testBootstrapHandler)

        // Serves files from the root of web_ui.
        //
        // This is needed because sourcemaps refer to local files, i.e. those
        // that don't come from package dependencies, relative to web_ui/.
        //
        // Examples of URLs that this handles:
        //  * /test/alarm_clock_test.dart
        //  * /lib/src/engine/alarm_clock.dart
        .add(createStaticHandler(env.environment.webUiRootDir.path))

        // Serves absolute package URLs (i.e. not /packages/* but /Users/user/*/hosted/pub.dartlang.org/*).
        // This handler goes last, after all more specific handlers failed to handle the request.
        .add(_createAbsolutePackageUrlHandler())
        .add(_screenshotHandler)

        // Generates and serves a test payload of given length, split into chunks
        // of given size. Reponds to requests to /long_test_payload.
        .add(_testPayloadGenerator)

        // If none of the handlers above handled the request, return 404.
        .add(_fileNotFoundCatcher);

    server.mount(cascade.handler);
  }

  /// Starts the server.
  ///
  /// [browserEnvironment] provides the browser environment to run the test.
  ///
  /// If [doUpdateScreenshotGoldens] is true updates screenshot golden files
  /// instead of failing the test on screenshot mismatches.
  static Future<BrowserPlatform> start({
    required BrowserEnvironment browserEnvironment,
    required Renderer renderer,
    required bool doUpdateScreenshotGoldens,
    required SkiaGoldClient? skiaClient,
    required String? overridePathToCanvasKit,
    required bool isWasm,
  }) async {
    final shelf_io.IOServer server =
        shelf_io.IOServer(await HttpMultiServer.loopback(0));
    return BrowserPlatform._(
      browserEnvironment: browserEnvironment,
      renderer: renderer,
      server: server,
      isDebug: Configuration.current.pauseAfterLoad,
      isWasm: isWasm,
      doUpdateScreenshotGoldens: doUpdateScreenshotGoldens,
      packageConfig: await loadPackageConfigUri((await Isolate.packageConfig)!),
      skiaClient: skiaClient,
      overridePathToCanvasKit: overridePathToCanvasKit,
    );
  }

  /// If true, runs the browser with a visible windows (i.e. not headless) and
  /// pauses before running the tests to give the developer a chance to set
  /// breakpoints in the code.
  final bool isDebug;

  final bool isWasm;

  /// The underlying server.
  final shelf.Server server;

  /// Provides the environment for the browser running tests.
  final BrowserEnvironment browserEnvironment;

  /// The renderer that tests are running under.
  final Renderer renderer;

  /// The URL for this server.
  Uri get url => server.url.resolve('/');

  /// A [OneOffHandler] for servicing WebSocket connections for
  /// [BrowserManager]s.
  ///
  /// This is one-off because each [BrowserManager] can only connect to a single
  /// WebSocket,
  final OneOffHandler _webSocketHandler = OneOffHandler();

  /// Whether [close] has been called.
  bool get _closed => _closeMemo.hasRun;

  /// Whether to update screenshot golden files.
  final bool doUpdateScreenshotGoldens;

  late final shelf.Handler _packageUrlHandler = packagesDirHandler();

  final PackageConfig packageConfig;

  /// A client for communicating with the Skia Gold backend to fetch, compare
  /// and update images.
  final SkiaGoldClient? skiaClient;

  final String? overridePathToCanvasKit;

  /// If a path to a custom local build of CanvasKit was specified, serve from
  /// there instead of serving the default CanvasKit in the build/ directory.
  Future<shelf.Response> _canvasKitOverrideHandler(
      shelf.Request request) async {
    final String? pathOverride = overridePathToCanvasKit;

    if (pathOverride == null || !request.url.path.startsWith('canvaskit/')) {
      return shelf.Response.notFound('Not a request for CanvasKit.');
    }

    final File file = File(p.joinAll(<String>[
      pathOverride,
      ...p.split(request.url.path).skip(1),
    ]));

    if (!file.existsSync()) {
      return shelf.Response.notFound('File not found: ${request.url.path}');
    }

    final String extension = p.extension(file.path);
    final String? contentType = contentTypes[extension];

    if (contentType == null) {
      final String error =
          'Failed to determine Content-Type for "${request.url.path}".';
      stderr.writeln(error);
      return shelf.Response.internalServerError(body: error);
    }

    return shelf.Response.ok(
      file.readAsBytesSync(),
      headers: <String, Object>{
        HttpHeaders.contentTypeHeader: contentType,
      },
    );
  }

  /// Lists available test images under `out/web_tests/test_images`.
  Future<shelf.Response> _testImageListingHandler(shelf.Request request) async {
    const Map<String, String> supportedImageTypes = <String, String>{
      '.png': 'image/png',
      '.jpg': 'image/jpeg',
      '.jpeg': 'image/jpeg',
      '.gif': 'image/gif',
      '.webp': 'image/webp',
      '.bmp': 'image/bmp',
    };

    if (request.url.path != 'test_images/') {
      return shelf.Response.notFound('Not found.');
    }

    final Directory testImageDirectory = Directory(p.join(
      env.environment.webUiBuildDir.path,
      'test_images',
    ));

    final List<String> testImageFiles = testImageDirectory
        .listSync(recursive: true)
        .whereType<File>()
        .map<String>(
            (File file) => p.relative(file.path, from: testImageDirectory.path))
        .where(
            (String path) => supportedImageTypes.containsKey(p.extension(path)))
        .toList();

    return shelf.Response.ok(
      json.encode(testImageFiles),
      headers: <String, Object>{
        HttpHeaders.contentTypeHeader: 'application/json',
      },
    );
  }

  Future<shelf.Response> _fileNotFoundCatcher(shelf.Request request) async {
    print('HTTP 404: ${request.url}');
    return shelf.Response.notFound('File not found');
  }

  /// Handles URLs pointing to Dart sources using absolute URI paths.
  ///
  /// Dart source paths that dart2js puts in source maps for pub packages are
  /// relative to the source map file. Example:
  ///
  ///     ../../../../../../../../../Users/yegor/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/src/frame.dart
  ///
  /// When the browser requests the file from the source map it sends a GET
  /// request like this:
  ///
  ///     GET /Users/yegor/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/src/frame.dart
  ///
  /// There's no predictable structure in this URL. It's unclear whether this
  /// is a request for a source file, or someone trying to hack your
  /// workstation.
  ///
  /// This handler treats the URL as an absolute path, but instead of
  /// unconditionally serving it, it first checks with `package_config.json` on
  /// whether this is a request for a Dart source that's listed in pubspec
  /// dependencies. For example, the `stack_trace` package would be listed in
  /// `package_config.json` as:
  ///
  ///     file:///C:/Users/yegor/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/stack_trace-1.10.0
  ///
  /// If the requested URL points into one of the packages in the package config,
  /// the file is served. Otherwise, HTTP 404 is returned without file contents.
  ///
  /// To handle drive letters (C:\) and *nix file system roots, the URL and
  /// package paths are initially stripped of the root and compared to each
  /// other as prefixes. To actually read the file, the file system root is
  /// prepended before creating the file.
  shelf.Handler _createAbsolutePackageUrlHandler() {
    final Map<String, Package> urlToPackage = <String, Package>{};
    for (final Package package in packageConfig.packages) {
      // Turns the URI as encoded in package_config.json to a file path.
      final String configPath = p.fromUri(package.root);

      // Strips drive letter and root prefix, if any, for example:
      //
      // C:\Users\user\AppData => Users\user\AppData
      // /home/user/path.dart => home/user/path.dart
      final String rootRelativePath =
          p.relative(configPath, from: p.rootPrefix(configPath));
      urlToPackage[p.toUri(rootRelativePath).path] = package;
    }
    return (shelf.Request request) async {
      final String requestedPath = request.url.path;
      // The cast is needed because keys are non-null String, so there's no way
      // to return null for a mismatch.
      final String? packagePath = urlToPackage.keys.cast<String?>().firstWhere(
            (String? packageUrl) => requestedPath.startsWith(packageUrl!),
            orElse: () => null,
          );
      if (packagePath == null) {
        return shelf.Response.notFound('Not a pub.dartlang.org request');
      }

      // Attach the root prefix, such as drive letter, and convert from URI to path.
      // Examples:
      //
      // Users\user\AppData => C:\Users\user\AppData
      // home/user/path.dart => /home/user/path.dart
      final Package package = urlToPackage[packagePath]!;
      final String filePath = p.join(
        p.rootPrefix(p.fromUri(package.root.path)),
        p.fromUri(requestedPath),
      );
      final File fileInPackage = File(filePath);
      if (!fileInPackage.existsSync()) {
        return shelf.Response.notFound('File not found: $requestedPath');
      }
      return shelf.Response.ok(fileInPackage.openRead());
    };
  }

  Future<shelf.Response> _testPayloadGenerator(shelf.Request request) async {
    if (!request.requestedUri.path.endsWith('/long_test_payload')) {
      return shelf.Response.notFound(
          'This request is not handled by the test payload generator');
    }

    final int payloadLength = int.parse(request.requestedUri.queryParameters['length']!);
    final int chunkLength = int.parse(request.requestedUri.queryParameters['chunk']!);

    final StreamController<List<int>> controller = StreamController<List<int>>();

    Future<void> fillPayload() async {
      int remainingByteCount = payloadLength;
      int byteCounter = 0;
      while (remainingByteCount > 0) {
        final int currentChunkLength = min(chunkLength, remainingByteCount);
        final List<int> chunk = List<int>.generate(
          currentChunkLength,
          (int i) => (byteCounter + i) & 0xFF,
        );
        byteCounter = (byteCounter + currentChunkLength) & 0xFF;
        remainingByteCount -= currentChunkLength;
        controller.add(chunk);
        await Future<void>.delayed(const Duration(milliseconds: 100));
      }
      await controller.close();
    }

    // Kick off payload filling function but don't block on it. The stream should
    // be returned immediately, and the client should receive data in chunks.
    unawaited(fillPayload());
    return shelf.Response.ok(
      controller.stream,
      headers: <String, String>{
        'Content-Type': 'application/octet-stream',
        'Content-Length': '$payloadLength',
      },
    );
  }

  Future<shelf.Response> _screenshotHandler(shelf.Request request) async {
    if (!request.requestedUri.path.endsWith('/screenshot')) {
      return shelf.Response.notFound(
          'This request is not handled by the screenshot handler');
    }

    final String payload = await request.readAsString();
    final Map<String, dynamic> requestData =
        json.decode(payload) as Map<String, dynamic>;
    final String filename = requestData['filename'] as String;

    if (!(await browserManager).supportsScreenshots) {
      print(
        'Skipping screenshot check for $filename. Current browser/OS '
        'combination does not support screenshots.',
      );
      return shelf.Response.ok(json.encode('OK'));
    }

    final Map<String, dynamic> region =
        requestData['region'] as Map<String, dynamic>;
    final bool isCanvaskitTest = requestData['isCanvaskitTest'] as bool;
    final String result = await _diffScreenshot(filename, region, isCanvaskitTest);
    return shelf.Response.ok(json.encode(result));
  }

  Future<String> _diffScreenshot(
    String filename,
    Map<String, dynamic> region,
    bool isCanvaskitTest,
  ) async {
    final Rectangle<num> regionAsRectange = Rectangle<num>(
      region['x'] as num,
      region['y'] as num,
      region['width'] as num,
      region['height'] as num,
    );

    // Take screenshot.
    final Image screenshot =
        await (await browserManager).captureScreenshot(regionAsRectange);

    return compareImage(
      screenshot,
      doUpdateScreenshotGoldens,
      filename,
      skiaClient,
      isCanvaskitTest: isCanvaskitTest,
    );
  }

  static const Map<String, String> contentTypes = <String, String>{
    '.js': 'text/javascript',
    '.mjs': 'text/javascript',
    '.wasm': 'application/wasm',
    '.html': 'text/html',
    '.htm': 'text/html',
    '.css': 'text/css',
    '.ico': 'image/icon-x',
    '.png': 'image/png',
    '.jpg': 'image/jpeg',
    '.jpeg': 'image/jpeg',
    '.gif': 'image/gif',
    '.webp': 'image/webp',
    '.bmp': 'image/bmp',
    '.svg': 'image/svg+xml',
    '.json': 'application/json',
    '.ttf': 'font/ttf',
    '.woff': 'font/woff',
    '.woff2': 'font/woff2',
  };

  /// A simple file handler that serves files whose URLs and paths are
  /// statically known.
  ///
  /// This is used for trivial use-cases, such as `favicon.ico`, host pages, etc.
  shelf.Response buildDirectoryHandler(shelf.Request request) {
    File fileInBuild = File(p.join(
      env.environment.webUiBuildDir.path,
      getBuildDirForRenderer(renderer),
      request.url.path,
    ));

    // If we can't find the file in the renderer-specific `build` subdirectory,
    // then it may be in the top-level `build` subdirectory.
    if (!fileInBuild.existsSync()) {
      fileInBuild = File(p.join(
        env.environment.webUiBuildDir.path,
        request.url.path,
      ));
    }

    if (!fileInBuild.existsSync()) {
      return shelf.Response.notFound('File not found: ${request.url.path}');
    }

    final String extension = p.extension(fileInBuild.path);
    final String? contentType = contentTypes[extension];

    if (contentType == null) {
      final String error =
          'Failed to determine Content-Type for "${request.url.path}".';
      stderr.writeln(error);
      return shelf.Response.internalServerError(body: error);
    }

    final bool needsCoopCoep =
      extension == '.js' ||
      extension == '.mjs' ||
      extension == '.html';
    return shelf.Response.ok(
      fileInBuild.readAsBytesSync(),
      headers: <String, Object>{
        HttpHeaders.contentTypeHeader: contentType,
        if (needsCoopCoep && isWasm && renderer == Renderer.skwasm)
          ...coopCoepHeaders,
      },
    );
  }

  /// Serves the HTML file that bootstraps the test.
  shelf.Response _testBootstrapHandler(shelf.Request request) {
    final String path = p.fromUri(request.url);

    if (path.endsWith('.html')) {
      final String test = '${p.withoutExtension(path)}.dart';

      // Link to the Dart wrapper.
      final String scriptBase = htmlEscape.convert(p.basename(test));
      final String link = '<link rel="x-dart-test" href="$scriptBase"${renderer == Renderer.skwasm ? " skwasm" : ""}>';

      final String testRunner = isWasm ? '/test_dart2wasm.js' : 'packages/test/dart.js';

      return shelf.Response.ok('''
        <!DOCTYPE html>
        <html>
        <head>
          <title>${htmlEscape.convert(test)} Test</title>
          <meta name="assetBase" content="/">
          <script>
            window.flutterConfiguration = {
              canvasKitBaseUrl: "/canvaskit/"
            };
          </script>
          $link
          <script src="$testRunner"></script>
        </head>
        </html>
      ''', headers: <String, String>{
        'Content-Type': 'text/html',
        if (isWasm && renderer == Renderer.skwasm)
          ...coopCoepHeaders
      });
    }

    return shelf.Response.notFound('Not found.');
  }

  void _checkNotClosed() {
    if (_closed) {
      throw StateError('Cannot load test suite. Test platform is closed.');
    }
  }

  /// Loads the test suite at [path] on the platform [platform].
  ///
  /// This will start a browser to load the suite if one isn't already running.
  /// Throws an [ArgumentError] if `platform.platform` isn't a browser.
  @override
  Future<RunnerSuite> load(String path, SuitePlatform platform,
      SuiteConfiguration suiteConfig, Object message) async {
    _checkNotClosed();
    if (suiteConfig.precompiledPath == null) {
      throw Exception('This test platform only supports precompiled JS.');
    }
    final Runtime browser = platform.runtime;
    assert(suiteConfig.runtimes.contains(browser.identifier));

    if (!browser.isBrowser) {
      throw ArgumentError('$browser is not a browser.');
    }
    _checkNotClosed();

    final Uri suiteUrl = url.resolveUri(p.toUri('${p.withoutExtension(
            p.relative(path, from: env.environment.webUiRootDir.path))}.html'));
    _checkNotClosed();

    final BrowserManager? browserManager = await _startBrowserManager();
    if (browserManager == null) {
      throw StateError(
          'Failed to initialize browser manager for ${browserEnvironment.name}');
    }
    _checkNotClosed();

    final RunnerSuite suite =
        await browserManager.load(path, suiteUrl, suiteConfig, message);
    _checkNotClosed();
    return suite;
  }

  Future<BrowserManager?>? _browserManager;
  Future<BrowserManager> get browserManager async => (await _browserManager!)!;

  /// Starts a browser manager for the browser provided by [browserEnvironment];
  ///
  /// If no browser manager is running yet, starts one.
  Future<BrowserManager?> _startBrowserManager() {
    if (_browserManager != null) {
      return _browserManager!;
    }

    final Completer<WebSocketChannel> completer =
        Completer<WebSocketChannel>.sync();
    final String path =
        _webSocketHandler.create(webSocketHandler(completer.complete));
    final Uri webSocketUrl = url.replace(scheme: 'ws').resolve(path);
    final Uri hostUrl = url.resolve('host/index.html').replace(
        queryParameters: <String, dynamic>{
          'managerUrl': webSocketUrl.toString(),
          'debug': isDebug.toString()
        });

    final Future<BrowserManager?> future = BrowserManager.start(
      browserEnvironment: browserEnvironment,
      url: hostUrl,
      future: completer.future,
      packageConfig: packageConfig,
      isWasm: isWasm,
      debug: isDebug,
      renderer: renderer,
    );

    // Store null values for browsers that error out so we know not to load them
    // again.
    _browserManager = future.catchError((dynamic _) => null);

    return future;
  }

  /// Close all the browsers that the server currently has open.
  ///
  /// Note that this doesn't close the server itself. Browser tests can still be
  /// loaded, they'll just spawn new browsers.
  @override
  Future<void> closeEphemeral() async {
    if (_browserManager != null) {
      final BrowserManager? result = await _browserManager;
      await result?.close();
    }
  }

  /// Closes the server and releases all its resources.
  ///
  /// Returns a [Future] that completes once the server is closed and its
  /// resources have been fully released.
  @override
  Future<void> close() {
    return _closeMemo.runOnce(() async {
      final List<Future<void>> futures = <Future<void>>[];
      futures.add(Future<void>.microtask(() async {
        if (_browserManager != null) {
          final BrowserManager? result = await _browserManager;
          await result?.close();
        }
      }));
      futures.add(server.close());

      await Future.wait(futures);
    });
  }

  final AsyncMemoizer<dynamic> _closeMemo = AsyncMemoizer<dynamic>();
}

/// A Shelf handler that provides support for one-time handlers.
///
/// This is useful for handlers that only expect to be hit once before becoming
/// invalid and don't need to have a persistent URL.
class OneOffHandler {
  /// A map from URL paths to handlers.
  final Map<String, shelf.Handler> _handlers = <String, shelf.Handler>{};

  /// The counter of handlers that have been activated.
  int _counter = 0;

  /// The actual [shelf.Handler] that dispatches requests.
  shelf.Handler get handler => _onRequest;

  /// Creates a new one-off handler that forwards to [handler].
  ///
  /// Returns a string that's the URL path for hitting this handler, relative to
  /// the URL for the one-off handler itself.
  ///
  /// [handler] will be unmounted as soon as it receives a request.
  String create(shelf.Handler handler) {
    final String path = _counter.toString();
    _handlers[path] = handler;
    _counter++;
    return path;
  }

  /// Dispatches [request] to the appropriate handler.
  FutureOr<shelf.Response> _onRequest(shelf.Request request) {
    final List<String> components = p.url.split(request.url.path);
    if (components.isEmpty) {
      return shelf.Response.notFound(null);
    }

    final String path = components.removeAt(0);
    final shelf.Handler? handler = _handlers.remove(path);
    if (handler == null) {
      return shelf.Response.notFound(null);
    }
    return handler(request.change(path: path));
  }
}

/// Manages the connection to a single running browser.
///
/// This is in charge of telling the browser which test suites to load and
/// converting its responses into [Suite] objects.
class BrowserManager {
  /// Creates a new BrowserManager that communicates with the browser over
  /// [webSocket].
  BrowserManager._(this.packageConfig, this._browser, this._browserEnvironment,
      this._renderer, this._isWasm, WebSocketChannel webSocket) {
    // The duration should be short enough that the debugging console is open as
    // soon as the user is done setting breakpoints, but long enough that a test
    // doing a lot of synchronous work doesn't trigger a false positive.
    //
    // Start this canceled because we don't want it to start ticking until we
    // get some response from the iframe.
    _timer = RestartableTimer(const Duration(seconds: 3), () {
      for (final RunnerSuiteController controller in _controllers) {
        controller.setDebugging(true);
      }
    })
      ..cancel();

    // Whenever we get a message, no matter which child channel it's for, we the
    // know browser is still running code which means the user isn't debugging.
    _channel = MultiChannel<dynamic>(webSocket
        .cast<String>()
        .transform(jsonDocument)
        .changeStream((Stream<Object?> stream) {
      return stream.map((Object? message) {
        if (!_closed) {
          _timer.reset();
        }
        for (final RunnerSuiteController controller in _controllers) {
          controller.setDebugging(false);
        }

        return message;
      });
    }));

    _environment = _loadBrowserEnvironment();
    _channel.stream.listen(
        (dynamic message) => _onMessage(message as Map<dynamic, dynamic>),
        onDone: close);
  }

  final PackageConfig packageConfig;

  /// The browser instance that this is connected to via [_channel].
  final Browser _browser;

  /// The browser environment for this test.
  final BrowserEnvironment _browserEnvironment;

  /// The renderer for this test.
  final Renderer _renderer;

  /// The channel used to communicate with the browser.
  ///
  /// This is connected to a page running `static/host.dart`.
  late final MultiChannel<dynamic> _channel;

  /// A pool that ensures that limits the number of initial connections the
  /// manager will wait for at once.
  ///
  /// This isn't the *total* number of connections; any number of iframes may be
  /// loaded in the same browser. However, the browser can only load so many at
  /// once, and we want a timeout in case they fail so we only wait for so many
  /// at once.
  final Pool _pool = Pool(8);

  /// The ID of the next suite to be loaded.
  ///
  /// This is used to ensure that the suites can be referred to consistently
  /// across the client and server.
  int _suiteID = 0;

  /// Whether the channel to the browser has closed.
  bool _closed = false;

  /// Whether we are running tests that have been compiled to WebAssembly.
  final bool _isWasm;

  /// The completer for [_BrowserEnvironment.displayPause].
  ///
  /// This will be `null` as long as the browser isn't displaying a pause
  /// screen.
  CancelableCompleter<void>? _pauseCompleter;

  /// The controller for [_BrowserEnvironment.onRestart].
  final StreamController<dynamic> _onRestartController =
      StreamController<dynamic>.broadcast();

  /// The environment to attach to each suite.
  late final Future<_BrowserEnvironment> _environment;

  /// Controllers for every suite in this browser.
  ///
  /// These are used to mark suites as debugging or not based on the browser's
  /// pings.
  final Set<RunnerSuiteController> _controllers = <RunnerSuiteController>{};

  // A timer that's reset whenever we receive a message from the browser.
  //
  // Because the browser stops running code when the user is actively debugging,
  // this lets us detect whether they're debugging reasonably accurately.
  late final RestartableTimer _timer;

  /// Starts the browser identified by [runtime] and has it connect to [url].
  ///
  /// [url] should serve a page that establishes a WebSocket connection with
  /// this process. That connection, once established, should be emitted via
  /// [future]. If [debug] is true, starts the browser in debug mode, with its
  /// debugger interfaces on and detected.
  ///
  /// The [settings] indicate how to invoke this browser's executable.
  ///
  /// Returns the browser manager, or throws an [Exception] if a
  /// connection fails to be established.
  static Future<BrowserManager?> start({
    required BrowserEnvironment browserEnvironment,
    required Uri url,
    required Future<WebSocketChannel> future,
    required PackageConfig packageConfig,
    required Renderer renderer,
    required bool isWasm,
    bool debug = false,
  }) async {
    final Browser browser =
        await _newBrowser(url, browserEnvironment, debug: debug);
    return _startBrowserManager(
        browserEnvironment: browserEnvironment,
        url: url,
        future: future,
        packageConfig: packageConfig,
        browser: browser,
        renderer: renderer,
        isWasm: isWasm,
        debug: debug);
  }

  static Future<BrowserManager?> _startBrowserManager({
    required BrowserEnvironment browserEnvironment,
    required Uri url,
    required Future<WebSocketChannel> future,
    required PackageConfig packageConfig,
    required Browser browser,
    required Renderer renderer,
    required bool isWasm,
    bool debug = false,
  }) {
    final Completer<BrowserManager> completer = Completer<BrowserManager>();

    // For the cases where we use a delegator such as `adb` (for Android) or
    // `xcrun` (for IOS), these delegator processes can shut down before the
    // websocket is available. Therefore do not throw an error if process
    // exits with exitCode 0. Note that `browser` will throw and error if the
    // exit code was not 0, which will be processed by the next callback.
    browser.onExit.catchError((Object error, StackTrace stackTrace) {
      if (completer.isCompleted) {
        return;
      }
      completer.completeError(error, stackTrace);
    });

    future.then((WebSocketChannel webSocket) {
      if (completer.isCompleted) {
        return;
      }
      completer.complete(BrowserManager._(
          packageConfig, browser, browserEnvironment, renderer, isWasm, webSocket));
    }).catchError((Object error, StackTrace stackTrace) {
      browser.close();
      if (completer.isCompleted) {
        return null;
      }
      completer.completeError(error, stackTrace);
    });

    return completer.future;
  }

  /// Starts the browser and requests that it load the test page at [url].
  ///
  /// If [debug] is true, starts the browser in debug mode.
  static Future<Browser> _newBrowser(
      Uri url, BrowserEnvironment browserEnvironment,
      {bool debug = false}) {
    return browserEnvironment.launchBrowserInstance(url, debug: debug);
  }

  /// Loads [_BrowserEnvironment].
  Future<_BrowserEnvironment> _loadBrowserEnvironment() async {
    return _BrowserEnvironment(this, await _browser.vmServiceUrl,
        await _browser.remoteDebuggerUrl, _onRestartController.stream);
  }

  /// Tells the browser the load a test suite from the URL [url].
  ///
  /// [url] should be an HTML page with a reference to the JS-compiled test
  /// suite. [path] is the path of the original test suite file, which is used
  /// for reporting. [suiteConfig] is the configuration for the test suite.
  Future<RunnerSuite> load(String path, Uri url, SuiteConfiguration suiteConfig,
      Object message) async {
    url = url.replace(
        fragment: Uri.encodeFull(jsonEncode(<String, dynamic>{
      'metadata': suiteConfig.metadata.serialize(),
      'browser': _browserEnvironment.packageTestRuntime.identifier
    })));

    final int suiteID = _suiteID++;
    RunnerSuiteController? controller;
    void closeIframe() {
      if (_closed) {
        return;
      }
      _controllers.remove(controller);
      _channel.sink
          .add(<String, dynamic>{'command': 'closeSuite', 'id': suiteID});
    }

    // The virtual channel will be closed when the suite is closed, in which
    // case we should unload the iframe.
    final VirtualChannel<dynamic> virtualChannel = _channel.virtualChannel();
    final int suiteChannelID = virtualChannel.id;
    final StreamChannel<dynamic> suiteChannel = virtualChannel.transformStream(
        StreamTransformer<dynamic, dynamic>.fromHandlers(
            handleDone: (EventSink<dynamic> sink) {
      closeIframe();
      sink.close();
    }));

    if (Configuration.current.pauseAfterLoad) {
      print('Browser loaded. Press enter to start tests...');
      stdin.readLineSync();
    }

    return _pool.withResource<RunnerSuite>(() async {
      _channel.sink.add(<String, dynamic>{
        'command': 'loadSuite',
        'url': url.toString(),
        'id': suiteID,
        'channel': suiteChannelID
      });

      try {
        controller = deserializeSuite(
            path,
            currentPlatform(_browserEnvironment.packageTestRuntime),
            suiteConfig,
            await _environment,
            suiteChannel,
            message);

        if (_isWasm) {
          // We don't have mapping for wasm yet. But we should send a message
          // to let the host page move forward.
          controller!.channel('test.browser.mapper').sink.add(null);
        } else {
          final String sourceMapFileName =
              '${p.basename(path)}.browser_test.dart.js.map';
          final String pathToTest = p.dirname(path);

          final String mapPath = p.join(env.environment.webUiBuildDir.path,
              getBuildDirForRenderer(_renderer), pathToTest, sourceMapFileName);

          final Map<String, Uri> packageMap = <String, Uri>{
            for (Package p in packageConfig.packages) p.name: p.packageUriRoot
          };
          final JSStackTraceMapper mapper = JSStackTraceMapper(
            await File(mapPath).readAsString(),
            mapUrl: p.toUri(mapPath),
            packageMap: packageMap,
            sdkRoot: p.toUri(sdkDir),
          );

          controller!.channel('test.browser.mapper').sink.add(mapper.serialize());
        }

        _controllers.add(controller!);
        return await controller!.suite;
      } catch (_) {
        closeIframe();
        rethrow;
      }
    });
  }

  /// An implementation of [Environment.displayPause].
  CancelableOperation<void> _displayPause() {
    CancelableCompleter<void>? pauseCompleter = _pauseCompleter;
    if (pauseCompleter != null) {
      return pauseCompleter.operation;
    }

    pauseCompleter = CancelableCompleter<void>(onCancel: () {
      _channel.sink.add(<String, String>{'command': 'resume'});
      _pauseCompleter = null;
    });
    _pauseCompleter = pauseCompleter;

    pauseCompleter.operation.value.whenComplete(() {
      _pauseCompleter = null;
    });

    _channel.sink.add(<String, String>{'command': 'displayPause'});

    return pauseCompleter.operation;
  }

  /// The callback for handling messages received from the host page.
  void _onMessage(Map<dynamic, dynamic> message) {
    switch (message['command'] as String) {
      case 'ping':
        break;

      case 'restart':
        _onRestartController.add(null);
        break;

      case 'resume':
        _pauseCompleter?.complete();
        break;

      default:
        // Unreachable.
        assert(false);
        break;
    }
  }

  bool get supportsScreenshots => _browser.supportsScreenshots;

  Future<Image> captureScreenshot(Rectangle<num> region) =>
      _browser.captureScreenshot(region);

  /// Closes the manager and releases any resources it owns, including closing
  /// the browser.
  Future<void> close() => _closeMemoizer.runOnce(() {
        if (Configuration.current.pauseAfterLoad) {
          print('Test run finished. Press enter to close browser...');
          stdin.readLineSync();
        }
        _closed = true;
        _timer.cancel();
        _pauseCompleter?.complete();
        _pauseCompleter = null;
        _controllers.clear();
        return _browser.close();
      });
  final AsyncMemoizer<dynamic> _closeMemoizer = AsyncMemoizer<dynamic>();
}

/// An implementation of [Environment] for the browser.
///
/// All methods forward directly to [BrowserManager].
class _BrowserEnvironment implements Environment {
  _BrowserEnvironment(this._manager, this.observatoryUrl,
      this.remoteDebuggerUrl, this.onRestart);

  final BrowserManager _manager;

  @override
  final bool supportsDebugging = true;

  @override
  final Uri? observatoryUrl;

  @override
  final Uri? remoteDebuggerUrl;

  @override
  final Stream<dynamic> onRestart;

  @override
  CancelableOperation<void> displayPause() => _manager._displayPause();
}

bool get isCirrus => Platform.environment['CIRRUS_CI'] == 'true';
