// Copyright (c) 2015, 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 'package:async/async.dart';
import 'package:pool/pool.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:test_api/backend.dart' show Compiler, Runtime, StackTraceMapper;
import 'package:test_core/src/runner/application_exception.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/configuration.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/environment.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/load_exception.dart'; // ignore: implementation_imports
import 'package:test_core/src/runner/plugin/platform_helpers.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/util/io.dart'; // ignore: implementation_imports
import 'package:web_socket_channel/web_socket_channel.dart';

import '../executable_settings.dart';
import 'browser.dart';
import 'chrome.dart';
import 'firefox.dart';
import 'microsoft_edge.dart';
import 'safari.dart';

/// A class that 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 {
  /// The browser instance that this is connected to via [_channel].
  final Browser _browser;

  // TODO(nweiz): Consider removing the duplication between this and
  // [_browser.name].
  /// The [Runtime] for [_browser].
  final Runtime _runtime;

  /// The channel used to communicate with the browser.
  ///
  /// This is connected to a page running `static/host.dart`.
  late final MultiChannel<Object> _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(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;

  /// 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 _onRestartController = StreamController<void>.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 _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 [ApplicationException] if a
  /// connection fails to be established.
  static Future<BrowserManager> start(
    Runtime runtime,
    Uri url,
    Future<WebSocketChannel> future,
    ExecutableSettings settings,
    Configuration configuration,
  ) => _start(runtime, url, future, settings, configuration, 1);

  static const _maxRetries = 3;
  static Future<BrowserManager> _start(
    Runtime runtime,
    Uri url,
    Future<WebSocketChannel> future,
    ExecutableSettings settings,
    Configuration configuration,
    int attempt,
  ) {
    var browser = _newBrowser(url, runtime, settings, configuration);

    var completer = Completer<BrowserManager>();

    // TODO(nweiz): Gracefully handle the browser being killed before the
    // tests complete.
    browser.onExit
        .then<void>(
          (_) => throw ApplicationException(
            '${runtime.name} exited before connecting.',
          ),
        )
        .onError<Object>((error, stackTrace) {
          if (!completer.isCompleted) {
            completer.completeError(error, stackTrace);
          }
        });

    future
        .then((webSocket) {
          if (completer.isCompleted) return;
          completer.complete(BrowserManager._(browser, runtime, webSocket));
        })
        .onError((Object error, StackTrace stackTrace) {
          browser.close();
          if (completer.isCompleted) return;
          completer.completeError(error, stackTrace);
        });

    return completer.future.timeout(
      const Duration(seconds: 30),
      onTimeout: () {
        browser.close();
        if (attempt >= _maxRetries) {
          throw ApplicationException(
            'Timed out waiting for ${runtime.name} to connect.\n'
            'Browser output: ${browser.output.join('\n')}',
          );
        }
        return _start(runtime, url, future, settings, configuration, ++attempt);
      },
    );
  }

  /// Starts the browser identified by [browser] using [settings] and has it load [url].
  ///
  /// If [debug] is true, starts the browser in debug mode.
  static Browser _newBrowser(
    Uri url,
    Runtime browser,
    ExecutableSettings settings,
    Configuration configuration,
  ) => switch (browser.root) {
    Runtime.chrome => Chrome(url, configuration, settings: settings),
    Runtime.firefox => Firefox(url, settings: settings),
    Runtime.safari => Safari(url, settings: settings),
    Runtime.edge => MicrosoftEdge(url, configuration, settings: settings),
    _ => throw ArgumentError('$browser is not a browser.'),
  };

  /// Creates a new BrowserManager that communicates with [browser] over
  /// [webSocket].
  BrowserManager._(this._browser, this._runtime, 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 (var 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(
      webSocket.cast<String>().transform(jsonDocument).changeStream((stream) {
        return stream.map((message) {
          if (!_closed) _timer.reset();
          for (var controller in _controllers) {
            controller.setDebugging(false);
          }

          return message;
        });
      }),
    );

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

  /// Loads [_BrowserEnvironment].
  Future<_BrowserEnvironment> _loadBrowserEnvironment() async =>
      _BrowserEnvironment(
        this,
        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.
  ///
  /// If [mapper] is passed, it's used to map stack traces for errors coming
  /// from this test suite.
  Future<RunnerSuite> load(
    String path,
    Uri url,
    SuiteConfiguration suiteConfig,
    Map<String, Object?> message,
    Compiler compiler, {
    StackTraceMapper? mapper,
    Duration? timeout,
  }) async {
    url = url.replace(
      fragment: Uri.encodeFull(
        jsonEncode({
          'metadata': suiteConfig.metadata.serialize(),
          'browser': _runtime.identifier,
          'compiler': compiler.serialize(),
        }),
      ),
    );

    var suiteID = _suiteID++;
    RunnerSuiteController? controller;
    void closeIframe() {
      if (_closed) return;
      if (controller != null) _controllers.remove(controller);
      _channel.sink.add({'command': 'closeSuite', 'id': suiteID});
    }

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

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

      try {
        controller = deserializeSuite(
          path,
          currentPlatform(_runtime, compiler),
          suiteConfig,
          await _environment,
          suiteChannel.cast(),
          message,
          gatherCoverage: () async {
            var browser = _browser;
            if (browser is Chrome) return browser.gatherCoverage();
            return {};
          },
        );

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

        _controllers.add(controller!);
        return await controller!.suite;
      } catch (_) {
        closeIframe();
        rethrow;
      }
    });
    if (timeout != null) {
      suite = suite.timeout(
        timeout,
        onTimeout: () {
          throw LoadException(
            path,
            'Timed out waiting for browser to load test suite. '
            'Browser output: ${_browser.output.join('\n')}',
          );
        },
      );
    }
    return suite;
  }

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

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

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

    _channel.sink.add({'command': 'displayPause'});

    return pauseCompleter.operation;
  }

  /// The callback for handling messages received from the host page.
  void _onMessage(Map<Object, Object?> 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;
    }
  }

  /// Closes the manager and releases any resources it owns, including closing
  /// the browser.
  Future<void> close() => _closeMemoizer.runOnce(() {
    _closed = true;
    _timer.cancel();
    _pauseCompleter?.complete();
    _pauseCompleter = null;
    _controllers.clear();
    return _browser.close();
  });
  final _closeMemoizer = AsyncMemoizer<void>();
}

/// An implementation of [Environment] for the browser.
///
/// All methods forward directly to [BrowserManager].
class _BrowserEnvironment implements Environment {
  final BrowserManager _manager;

  @override
  final supportsDebugging = true;

  @override
  Null get observatoryUrl => null;

  @override
  final Uri? remoteDebuggerUrl;

  @override
  final Stream<void> onRestart;

  _BrowserEnvironment(this._manager, this.remoteDebuggerUrl, this.onRestart);

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