// 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.

// ignore_for_file: avoid_dynamic_calls

@JS()
library test.host;

import 'dart:async';
import 'dart:convert';
import 'dart:js_interop';

import 'package:stack_trace/stack_trace.dart';
import 'package:stream_channel/stream_channel.dart';
// ignore: implementation_imports
import 'package:ui/src/engine/dom.dart';

/// A class defined in content shell, used to control its behavior.
@JS()
@staticInterop
class _TestRunner {}

extension _TestRunnerExtension on _TestRunner {
  external JSVoid waitUntilDone();
}

/// Returns the current content shell runner, or `null` if none exists.
@JS()
external _TestRunner? get testRunner; // ignore: library_private_types_in_public_api

/// A class that exposes the test API to JS.
///
/// These are exposed so that tools like IDEs can interact with them via remote
/// debugging.
@JS()
@anonymous
@staticInterop
class _JSApi {
  external factory _JSApi({JSFunction resume, JSFunction restartCurrent});
}

extension _JSApiExtension on _JSApi {
  /// Causes the test runner to resume running, as though the user had clicked
  /// the "play" button.
  // ignore: unused_element
  external JSFunction get resume;

  /// Causes the test runner to restart the current test once it finishes
  /// running.
  // ignore: unused_element
  external JSFunction get restartCurrent;
}

/// Sets the top-level `dartTest` object so that it's visible to JS.
@JS('dartTest')
external set _jsApi(_JSApi api);

/// The iframes created for each loaded test suite, indexed by the suite id.
final Map<int, DomHTMLIFrameElement> _iframes = <int, DomHTMLIFrameElement>{};

/// Subscriptions created for each loaded test suite, indexed by the suite id.
final Map<int, List<DomSubscription>> _domSubscriptions = <int, List<DomSubscription>>{};
final Map<int, List<StreamSubscription<dynamic>>> _streamSubscriptions =<int, List<StreamSubscription<dynamic>>>{};

/// The URL for the current page.
final Uri _currentUrl = Uri.parse(domWindow.location.href);

/// Code that runs in the browser and loads test suites at the server's behest.
///
/// One instance of this runs for each browser. When the server tells it to load
/// a test, it starts an iframe pointing at that test's code; from then on, it
/// just relays messages between the two.
///
/// The browser uses two layers of [MultiChannel]s when communicating with the
/// server:
///
///                                       server
///                                         │
///                                    (WebSocket)
///                                         │
///                    ┏━ host.html ━━━━━━━━┿━━━━━━━━━━━━━━━━━┓
///                    ┃                    │                 ┃
///                    ┃    ┌──────┬───MultiChannel─────┐     ┃
///                    ┃    │      │      │      │      │     ┃
///                    ┃   host  suite  suite  suite  suite   ┃
///                    ┃           │      │      │      │     ┃
///                    ┗━━━━━━━━━━━┿━━━━━━┿━━━━━━┿━━━━━━┿━━━━━┛
///                                │      │      │      │
///                                │     ...    ...    ...
///                                │
///                         (MessageChannel)
///                                │
///      ┏━ suite.html (in iframe) ┿━━━━━━━━━━━━━━━━━━━━━━━━━━┓
///      ┃                         │                          ┃
///      ┃         ┌──────────MultiChannel┬─────────┐         ┃
///      ┃         │          │     │     │         │         ┃
///      ┃   IframeListener  test  test  test  running test   ┃
///      ┃                                                    ┃
///      ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
///
/// The host (this code) has a [MultiChannel] that splits the WebSocket
/// connection with the server. One connection is used for the host itself to
/// receive messages like "load a suite at this URL", and the rest are
/// connected to each test suite's iframe via a [MessageChannel].
///
/// Each iframe then has its own [MultiChannel] which takes its
/// [MessageChannel] connection and splits it again. One connection is used for
/// the [IframeListener], which sends messages like "here are all the tests in
/// this suite". The rest are used for each test, receiving messages like
/// "start running". A new connection is also created whenever a test begins
/// running to send status messages about its progress.
///
/// It's of particular note that the suite's [MultiChannel] connection uses the
/// host's purely as a transport layer; neither is aware that the other is also
/// using [MultiChannel]. This is necessary, since the host doesn't share memory
/// with the suites and thus can't share its [MultiChannel] with them, but it
/// does mean that the server needs to be sure to nest its [MultiChannel]s at
/// the same place the client does.
void main() {
  // This tells content_shell not to close immediately after the page has
  // rendered.
  testRunner?.waitUntilDone();

  if (_currentUrl.queryParameters['debug'] == 'true') {
    domDocument.body!.classList.add('debug');
  }

  runZonedGuarded(
    () {
      final MultiChannel<dynamic> serverChannel = _connectToServer();
      serverChannel.stream.listen((dynamic message) {
        if (message['command'] == 'loadSuite') {
          final int channelId = message['channel'] as int;
          final String url = message['url'] as String;
          final int messageId = message['id'] as int;
          final VirtualChannel<dynamic> suiteChannel = serverChannel.virtualChannel(channelId);
          final StreamChannel<dynamic> iframeChannel = _connectToIframe(url, messageId);
          suiteChannel.pipe(iframeChannel);
        } else if (message['command'] == 'displayPause') {
          domDocument.body!.classList.add('paused');
        } else if (message['command'] == 'resume') {
          domDocument.body!.classList.remove('paused');
        } else {
          assert(message['command'] == 'closeSuite');
          _iframes.remove(message['id'])!.remove();

          for (final DomSubscription subscription in _domSubscriptions.remove(message['id'])!) {
            subscription.cancel();
          }
          for (final StreamSubscription<dynamic> subscription in _streamSubscriptions.remove(message['id'])!) {
            subscription.cancel();
          }
        }
      });

      // Send periodic pings to the test runner so it can know when the browser is
      // paused for debugging.
      Timer.periodic(const Duration(seconds: 1),
          (_) => serverChannel.sink.add(<String, String>{'command': 'ping'}));

      _jsApi = _JSApi(resume: () {
        if (!domDocument.body!.classList.contains('paused')) {
          return;
        }
        domDocument.body!.classList.remove('paused');
        serverChannel.sink.add(<String, String>{'command': 'resume'});
      }.toJS, restartCurrent: () {
        serverChannel.sink.add(<String, String>{'command': 'restart'});
      }.toJS);
    },
    (dynamic error, StackTrace stackTrace) {
      print('$error\n${Trace.from(stackTrace).terse}'); // ignore: avoid_print
    },
  );
}

/// Creates a [MultiChannel] connection to the server, using a [WebSocket] as
/// the underlying protocol.
MultiChannel<dynamic> _connectToServer() {
  // The `managerUrl` query parameter contains the WebSocket URL of the remote
  // [BrowserManager] with which this communicates.
  final DomWebSocket webSocket = createDomWebSocket(_currentUrl.queryParameters['managerUrl']!);

  final StreamChannelController<dynamic> controller = StreamChannelController<dynamic>(sync: true);
  webSocket.addEventListener('message', createDomEventListener((DomEvent message) {
    final String data = (message as DomMessageEvent).data as String;
    controller.local.sink.add(jsonDecode(data));
  }));

  controller.local.stream
      .listen((dynamic message) => webSocket.send(jsonEncode(message)));

  return MultiChannel<dynamic>(controller.foreign);
}

/// Creates an iframe with `src` [url] and establishes a connection to it using
/// a [MessageChannel].
///
/// [id] identifies the suite loaded in this iframe.
StreamChannel<dynamic> _connectToIframe(String url, int id) {
  final DomHTMLIFrameElement iframe = createDomHTMLIFrameElement();
  _iframes[id] = iframe;
  iframe
    ..src = url
    ..width = '1000'
    ..height = '1000';
  domDocument.body!.appendChild(iframe);

  // Use this to communicate securely with the iframe.
  final DomMessageChannel channel = createDomMessageChannel();
  final StreamChannelController<dynamic> controller = StreamChannelController<dynamic>(sync: true);

  // Use this to avoid sending a message to the iframe before it's sent a
  // message to us. This ensures that no messages get dropped on the floor.
  final Completer<dynamic> readyCompleter = Completer<dynamic>();

  final List<DomSubscription> domSubscriptions = <DomSubscription>[];
  final List<StreamSubscription<dynamic>> streamSubscriptions = <StreamSubscription<dynamic>>[];
  _domSubscriptions[id] = domSubscriptions;
  _streamSubscriptions[id] = streamSubscriptions;
  domSubscriptions.add(DomSubscription(domWindow, 'message',
          (DomEvent event) {
    final DomMessageEvent message = event as DomMessageEvent;
    // A message on the Window can theoretically come from any website. It's
    // very unlikely that a malicious site would care about hacking someone's
    // unit tests, let alone be able to find the test server while it's
    // running, but it's good practice to check the origin anyway.
    if (message.origin != domWindow.location.origin) {
      return;
    }

    if (message.data['href'] != iframe.src) {
      return;
    }

    message.stopPropagation();

    if (message.data['ready'] == true) {
      // This message indicates that the iframe is actively listening for
      // events, so the message channel's second port can now be transferred.
      channel.port2.start();
      iframe.contentWindow.postMessage('port', domWindow.location.origin,
          <DomMessagePort>[channel.port2]);
      readyCompleter.complete();
    } else if (message.data['exception'] == true) {
      // This message from `dart.js` indicates that an exception occurred
      // loading the test.
      controller.local.sink.add(message.data['data']);
    }
  }));

  channel.port1.start();
  domSubscriptions.add(DomSubscription(channel.port1, 'message',
          (DomEvent message) {
    controller.local.sink.add((message as DomMessageEvent).data['data']);
  }));

  streamSubscriptions.add(controller.local.stream.listen((dynamic message) async {
    await readyCompleter.future;
    channel.port1.postMessage(message);
  }));

  return controller.foreign;
}
