// Copyright 2014 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:js_interop';
import 'dart:ui' as ui;
import 'dart:ui_web' as ui_web;

import 'package:stream_channel/stream_channel.dart';
import 'package:test_api/backend.dart';

import '_goldens_web.dart';
import 'goldens.dart';
import 'web.dart' as web;

// This file contains APIs that are used by the generated test harness for
// running flutter unit tests.

/// A `main` entry point for a test.
typedef EntryPoint = FutureOr<void> Function();

/// An entry point runner provided by a test config file
typedef EntryPointRunner = Future<void> Function(EntryPoint);

/// Metadata about a web test to run
typedef WebTest = ({
  EntryPoint entryPoint,
  EntryPointRunner? entryPointRunner,
  Uri goldensUri,
});

/// Gets the test selector set by the test bootstrapping logic
String get testSelector {
  final JSString? jsTestSelector = web.window.testSelector;
  if (jsTestSelector == null) {
    throw Exception('Test selector not set');
  }
  return  jsTestSelector.toDart;
}

/// Runs a specific web test
Future<void> runWebTest(WebTest test) async {
  ui_web.debugEmulateFlutterTesterEnvironment = true;
  final Completer<void> completer = Completer<void>();
  await ui_web.bootstrapEngine(runApp: () => completer.complete());
  await completer.future;
  webGoldenComparator = DefaultWebGoldenComparator(test.goldensUri);

  /// This hard-codes the device pixel ratio to 3.0 and a 2400 x 1800 window
  /// size for the purposes of testing.
  ui_web.debugOverrideDevicePixelRatio(3.0);
  ui.window.debugPhysicalSizeOverride = const ui.Size(2400, 1800);

  final EntryPointRunner? entryPointRunner = test.entryPointRunner;
  final EntryPoint entryPoint = test.entryPoint;
  _internalBootstrapBrowserTest(() {
    return entryPointRunner != null ? () => entryPointRunner(entryPoint) : entryPoint;
  });
}

void _internalBootstrapBrowserTest(EntryPoint Function() getMain) {
  final StreamChannel<Object?> channel = _serializeSuite(getMain, hidePrints: false);
  _postMessageChannel().pipe(channel);
}

StreamChannel<Object?> _serializeSuite(EntryPoint Function() getMain, {bool hidePrints = true}) => RemoteListener.start(getMain, hidePrints: hidePrints);

StreamChannel<Object?> _postMessageChannel() {
  final StreamChannelController<Object?> controller = StreamChannelController<Object?>(sync: true);
  final web.MessageChannel channel = web.MessageChannel();
  web.window.parent!.postMessage('port'.toJS, web.window.location.origin, <JSObject>[channel.port2].toJS);

  final JSFunction eventCallback = (web.Event event) {
    controller.local.sink.add(event.data.dartify());
  }.toJS;
  channel.port1.addEventListener('message'.toJS, eventCallback);
  channel.port1.start();
  controller.local.stream.listen(
    (Object? message) => channel.port1.postMessage(message.jsify()),
    onDone: () => channel.port1.removeEventListener('message'.toJS, eventCallback),
  );

  return controller.foreign;
}
