// Copyright (c) 2022, 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:async/async.dart';
import 'package:http_multi_server/http_multi_server.dart';
import 'package:path/path.dart' as p;
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:test_api/backend.dart' show Compiler, Runtime, SuitePlatform;
import 'package:test_core/src/runner/configuration.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/package_version.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/platform.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/plugin/customizable_platform.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/runner_suite.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/suite.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/wasm_compiler_pool.dart'; // ignore: implementation_imports
import 'package:test_core/src/util/io.dart'; // ignore: implementation_imports
import 'package:test_core/src/util/package_config.dart'; // ignore: implementation_imports
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:yaml/yaml.dart';

import '../../util/math.dart';
import '../../util/one_off_handler.dart';
import '../../util/path_handler.dart';
import '../browser/browser_manager.dart';
import '../executable_settings.dart';
import 'default_settings.dart';

class BrowserWasmPlatform extends PlatformPlugin
    implements CustomizablePlatform<ExecutableSettings> {
  /// Starts the server.
  ///
  /// [root] is the root directory that the server should serve. It defaults to
  /// the working directory.
  static Future<BrowserWasmPlatform> start({String? root}) async {
    print('WARNING: Running with the experimental wasm platform. This platform '
        'is temporary and will be removed in the future, without a breaking '
        'change release, in favor of a different method of running wasm tests.'
        'This platform should only be used for experimentation at this time.'
        '\n');
    var server = shelf_io.IOServer(await HttpMultiServer.loopback(0));
    var packageConfig = await currentPackageConfig;
    return BrowserWasmPlatform._(
        server,
        Configuration.current,
        p.fromUri(packageConfig.resolve(
            Uri.parse('package:test/src/runner/browser/static/favicon.ico'))),
        p.fromUri(packageConfig.resolve(
            Uri.parse('package:test/src/runner/wasm/static/default.html.tpl'))),
        p.fromUri(packageConfig.resolve(Uri.parse(
            'package:test/src/runner/wasm/static/run_wasm_chrome.js'))),
        root: root);
  }

  /// The test runner configuration.
  final Configuration _config;

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

  /// A randomly-generated secret.
  ///
  /// This is used to ensure that other users on the same system can't snoop
  /// on data being served through this server.
  final _secret = randomUrlSecret();

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

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

  /// A [PathHandler] used to serve compiled WASM tests.
  final _wasmHandler = PathHandler();

  /// The [WasmCompilerPool] managing active instances of `dart2wasm`.
  final _compilers = WasmCompilerPool();

  /// The temporary directory in which compiled WASM is emitted.
  final _compiledDir = createTempDir();

  /// The root directory served statically by this server.
  final String _root;

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

  /// A map from browser identifiers to futures that will complete to the
  /// [BrowserManager]s for those browsers, or `null` if they failed to load.
  ///
  /// This should only be accessed through [_browserManagerFor].
  final _browserManagers = <Runtime, Future<BrowserManager?>>{};

  /// Settings for invoking each browser.
  ///
  /// This starts out with the default settings, which may be overridden by user settings.
  final _browserSettings =
      Map<Runtime, ExecutableSettings>.from(defaultSettings);

  /// A map from test suite paths to Futures that will complete once those
  /// suites are finished compiling.
  ///
  /// This is used to make sure that a given test suite is only compiled once
  /// per run, rather than once per browser per run.
  final _compileFutures = <String, Future<void>>{};

  /// The default template for html tests.
  final String _defaultTemplatePath;

  /// The `package:test` side wrapper for the Dart2Wasm runtime.
  final String _jsRuntimeWrapper;

  BrowserWasmPlatform._(this._server, Configuration config, String faviconPath,
      this._defaultTemplatePath, this._jsRuntimeWrapper,
      {String? root})
      : _config = config,
        _root = root ?? p.current {
    var cascade = shelf.Cascade().add(_webSocketHandler.handler);

    if (_config.pubServeUrl != null) {
      throw UnsupportedError(
          'WASM browser tests don\'t support the `--pub-serve` argument');
    }

    cascade = cascade
        .add(packagesDirHandler())
        .add(_wasmHandler.handler)
        .add(createStaticHandler(_root))
        .add(_wrapperHandler);

    var pipeline = const shelf.Pipeline()
        .addMiddleware(PathHandler.nestedIn(_secret))
        .addHandler(cascade.handler);

    _server.mount(shelf.Cascade()
        .add(createFileHandler(faviconPath))
        .add(pipeline)
        .handler);
  }

  /// A handler that serves wrapper files used to bootstrap tests.
  shelf.Response _wrapperHandler(shelf.Request request) {
    var path = p.fromUri(request.url);

    if (path.endsWith('.html')) {
      var test = '${p.withoutExtension(path)}.dart';
      var scriptBase = htmlEscape.convert(p.basename(test));
      var link = '<link rel="x-dart-test" href="$scriptBase">';
      var testName = htmlEscape.convert(test);
      var template = _config.customHtmlTemplatePath ?? _defaultTemplatePath;
      var contents = File(template).readAsStringSync();
      var jsRuntime = p.basename('$test.browser_test.dart.mjs');
      var processedContents = contents
          // Checked during loading phase that there is only one {{testScript}} placeholder.
          .replaceFirst('{{testScript}}', link)
          .replaceFirst('{{jsRuntimeUrl}}', jsRuntime)
          .replaceFirst(
              '{{wasmUrl}}', p.basename('$test.browser_test.dart.wasm'))
          .replaceAll('{{testName}}', testName);
      return shelf.Response.ok(processedContents,
          headers: {'Content-Type': 'text/html'});
    }

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

  @override
  ExecutableSettings parsePlatformSettings(YamlMap settings) =>
      ExecutableSettings.parse(settings);

  @override
  ExecutableSettings mergePlatformSettings(
          ExecutableSettings settings1, ExecutableSettings settings2) =>
      settings1.merge(settings2);

  @override
  void customizePlatform(Runtime runtime, ExecutableSettings settings) {
    var oldSettings =
        _browserSettings[runtime] ?? _browserSettings[runtime.root];
    if (oldSettings != null) settings = oldSettings.merge(settings);
    _browserSettings[runtime] = settings;
  }

  /// 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, Map<String, Object?> message) async {
    if (platform.compiler != Compiler.dart2wasm) {
      throw StateError(
          'Unsupported compiler for experimental-chrome-wasm platform '
          '${platform.compiler}');
    }

    if (suiteConfig.precompiledPath != null) {
      throw UnsupportedError(
          'The wasm platform doesn\'t support precompiled suites');
    }
    var browser = platform.runtime;
    assert(suiteConfig.runtimes.contains(browser.identifier));

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

    // TODO: Support custom html?

    Uri suiteUrl;

    await _compileSuite(path, suiteConfig);

    if (_closed) return null;
    suiteUrl = url.resolveUri(
        p.toUri('${p.withoutExtension(p.relative(path, from: _root))}.html'));

    if (_closed) return null;

    var browserManager = await _browserManagerFor(browser);
    if (_closed || browserManager == null) return null;

    var suite = await browserManager.load(
        path, suiteUrl, suiteConfig, message, platform.compiler);
    if (_closed) return null;
    return suite;
  }

  /// Compile the test suite at [dartPath] to WASM.
  ///
  /// Once the suite has been compiled, it's added to [_wasmHandler] so it can be
  /// served.
  Future<void> _compileSuite(String dartPath, SuiteConfiguration suiteConfig) {
    return _compileFutures.putIfAbsent(dartPath, () async {
      var dir = Directory(_compiledDir).createTempSync('test_').path;

      var baseCompiledPath =
          p.join(dir, '${p.basename(dartPath)}.browser_test.dart');
      var baseUrl =
          '${p.toUri(p.relative(dartPath, from: _root)).path}.browser_test.dart';
      var wasmUrl = '$baseUrl.wasm';
      var jsRuntimeWrapperUrl = '$baseUrl.js';
      var jsRuntimeUrl = '$baseUrl.mjs';
      var htmlUrl = '$baseUrl.html';

      var bootstrapContent = '''
        ${suiteConfig.metadata.languageVersionComment ?? await rootPackageLanguageVersionComment}
        import "package:test/src/bootstrap/browser.dart";

        import "${p.toUri(p.absolute(dartPath))}" as test;

        void main() {
          internalBootstrapBrowserTest(() => test.main);
        }
      ''';

      await _compilers.compile(bootstrapContent, baseCompiledPath, suiteConfig);
      if (_closed) return;

      var wasmPath = '$baseCompiledPath.wasm';
      _wasmHandler.add(wasmUrl, (request) {
        return shelf.Response.ok(File(wasmPath).readAsBytesSync(),
            headers: {'Content-Type': 'application/wasm'});
      });

      _wasmHandler.add(jsRuntimeWrapperUrl, (request) {
        return shelf.Response.ok(File(_jsRuntimeWrapper).readAsBytesSync(),
            headers: {'Content-Type': 'application/javascript'});
      });

      var jsRuntimePath = '$baseCompiledPath.mjs';
      _wasmHandler.add(jsRuntimeUrl, (request) {
        return shelf.Response.ok(File(jsRuntimePath).readAsBytesSync(),
            headers: {'Content-Type': 'application/javascript'});
      });

      var htmlPath = '$baseCompiledPath.html';
      _wasmHandler.add(htmlUrl, (request) {
        return shelf.Response.ok(File(htmlPath).readAsBytesSync(),
            headers: {'Content-Type': 'text/html'});
      });
    });
  }

  /// Returns the [BrowserManager] for [browser].
  ///
  /// If no browser manager is running yet, starts one.
  ///
  /// TODO: Share a browser manager with the regular browser platform.
  Future<BrowserManager?> _browserManagerFor(Runtime browser) {
    var managerFuture = _browserManagers[browser];
    if (managerFuture != null) return managerFuture;

    var completer = Completer<WebSocketChannel>.sync();
    var path = _webSocketHandler.create(webSocketHandler(completer.complete));
    var webSocketUrl = url.replace(scheme: 'ws').resolve(path);
    var hostUrl = url
        .resolve('packages/test/src/runner/browser/static/index.html')
        .replace(queryParameters: {
      'managerUrl': webSocketUrl.toString(),
      'debug': _config.debug.toString()
    });

    var future = BrowserManager.start(browser, hostUrl, completer.future,
            _browserSettings[browser]!, _config)
        .onError((error, _) {
      throw StateError('Unable to spawn Chrome Beta, which is required by the '
          'experimental-chrome-wasm platform. You may also need to set the '
          'executable path in your dart_test.yaml file, documented here: '
          'https://github.com/dart-lang/test/blob/master/pkgs/test/doc/configuration.md#override_platforms'
          '\n\n$error\n');
    });

    // Store null values for browsers that error out so we know not to load them
    // again.
    _browserManagers[browser] =
        future.then<BrowserManager?>((value) => value).onError((_, __) => 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<List<void>> closeEphemeral() {
    var managers = _browserManagers.values.toList();
    _browserManagers.clear();
    return Future.wait(managers.map((manager) async {
      var result = await manager;
      if (result == null) return;
      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() async => _closeMemo.runOnce(() async {
        await Future.wait([
          for (var browser in _browserManagers.values)
            browser.then((b) => b?.close()),
          _server.close(),
          _compilers.close(),
          Directory(_compiledDir).deleteWithRetry(),
        ]);
      });
  final _closeMemo = AsyncMemoizer<void>();
}
