// 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:typed_data';

import 'package:meta/meta.dart';
import 'package:ui/ui.dart' as ui;
import 'package:ui/ui_web/src/ui_web.dart' as ui_web;

import '../engine.dart' show DimensionsProvider, registerHotRestartListener, renderer;
import 'browser_detection.dart';
import 'configuration.dart';
import 'display.dart';
import 'dom.dart';
import 'initialization.dart';
import 'js_interop/js_app.dart';
import 'mouse/context_menu.dart';
import 'mouse/cursor.dart';
import 'navigation/history.dart';
import 'platform_dispatcher.dart';
import 'pointer_binding.dart';
import 'semantics.dart';
import 'services.dart';
import 'text_editing/text_editing.dart';
import 'util.dart';
import 'view_embedder/dom_manager.dart';
import 'view_embedder/embedding_strategy/embedding_strategy.dart';
import 'view_embedder/global_html_attributes.dart';
import 'view_embedder/style_manager.dart';

typedef _HandleMessageCallBack = Future<bool> Function();

/// When set to true, all platform messages will be printed to the console.
const bool debugPrintPlatformMessages = false;

/// The view ID for the implicit flutter view provided by the platform.
const int kImplicitViewId = 0;

int _nextViewId = kImplicitViewId + 1;

/// Represents all views in the Flutter Web Engine.
///
/// In addition to everything defined in [ui.FlutterView], this class adds
/// a few web-specific properties.
base class EngineFlutterView implements ui.FlutterView {
  /// Creates a [ui.FlutterView] that can be used in multi-view mode.
  ///
  /// The [hostElement] parameter specifies the container in the DOM into which
  /// the Flutter view will be rendered.
  factory EngineFlutterView(
    EnginePlatformDispatcher platformDispatcher,
    DomElement hostElement, {
      JsViewConstraints? viewConstraints,
    }
  ) = _EngineFlutterViewImpl;

  EngineFlutterView._(
    this.viewId,
    this.platformDispatcher,
    // This is nullable to accommodate the legacy `EngineFlutterWindow`. In
    // multi-view mode, the host element is required for each view (as reflected
    // by the public `EngineFlutterView` constructor).
    DomElement? hostElement, {
      JsViewConstraints? viewConstraints,
    }
  )   : _jsViewConstraints = viewConstraints,
        embeddingStrategy = EmbeddingStrategy.create(hostElement: hostElement),
        dimensionsProvider = DimensionsProvider.create(hostElement: hostElement) {
    // The embeddingStrategy will take care of cleaning up the rootElement on
    // hot restart.
    embeddingStrategy.attachViewRoot(dom.rootElement);
    pointerBinding = PointerBinding(this);
    _resizeSubscription = onResize.listen(_didResize);
    _globalHtmlAttributes.applyAttributes(
      viewId: viewId,
      autoDetectRenderer: FlutterConfiguration.flutterWebAutoDetect,
      rendererTag: renderer.rendererTag,
      buildMode: buildMode,
    );
    registerHotRestartListener(dispose);
  }

  static EngineFlutterWindow implicit(
    EnginePlatformDispatcher platformDispatcher,
    DomElement? hostElement,
  ) => EngineFlutterWindow._(platformDispatcher, hostElement);

  @override
  final int viewId;

  @override
  final EnginePlatformDispatcher platformDispatcher;

  /// Abstracts all the DOM manipulations required to embed a Flutter view in a user-supplied `hostElement`.
  final EmbeddingStrategy embeddingStrategy;

  late final StreamSubscription<ui.Size?> _resizeSubscription;

  final ViewConfiguration _viewConfiguration = const ViewConfiguration();

  /// Whether this [EngineFlutterView] has been disposed or not.
  bool isDisposed = false;

  /// Disposes of the [EngineFlutterView] instance and undoes all of its DOM
  /// tree and any event listeners.
  @mustCallSuper
  void dispose() {
    if (isDisposed) {
      return;
    }
    isDisposed = true;
    _resizeSubscription.cancel();
    dimensionsProvider.close();
    pointerBinding.dispose();
    dom.rootElement.remove();
    // TODO(harryterkelsen): What should we do about this in multi-view?
    renderer.clearFragmentProgramCache();
    semantics.reset();
  }

  @override
  void render(ui.Scene scene, {ui.Size? size}) {
    assert(!isDisposed, 'Trying to render a disposed EngineFlutterView.');
    if (size != null) {
      resize(size);
    }
    platformDispatcher.render(scene, this);
  }

  @override
  void updateSemantics(ui.SemanticsUpdate update) {
    assert(!isDisposed, 'Trying to update semantics on a disposed EngineFlutterView.');
    semantics.updateSemantics(update);
  }

  late final GlobalHtmlAttributes _globalHtmlAttributes = GlobalHtmlAttributes(
    rootElement: dom.rootElement,
    hostElement: embeddingStrategy.hostElement,
  );

  late final MouseCursor mouseCursor = MouseCursor(dom.rootElement);

  late final ContextMenu contextMenu = ContextMenu(dom.rootElement);

  late final DomManager dom = DomManager(devicePixelRatio: devicePixelRatio);

  late final PointerBinding pointerBinding;

  @override
  ViewConstraints get physicalConstraints {
    final double dpr = devicePixelRatio;
    final ui.Size currentLogicalSize = physicalSize / dpr;
    return ViewConstraints.fromJs(_jsViewConstraints, currentLogicalSize) * dpr;
  }

  final JsViewConstraints? _jsViewConstraints;

  late final EngineSemanticsOwner semantics = EngineSemanticsOwner(dom.semanticsHost);

  @override
  ui.Size get physicalSize {
    return _physicalSize ??= _computePhysicalSize();
  }

  /// Resizes the `rootElement` to `newPhysicalSize` by changing its CSS style.
  ///
  /// This is used by the [render] method, when the framework sends new dimensions
  /// for the current Flutter View.
  ///
  /// Dimensions from the framework are constrained by the [physicalConstraints]
  /// that can be configured by the user when adding a view to the app.
  ///
  /// In practice, this method changes the size of the `rootElement` of the app
  /// so it can push/shrink inside its `hostElement`. That way, a Flutter app
  /// can change the layout of the container page.
  ///
  /// ```none
  /// <p>Some HTML content...</p>
  /// +--- (div) hostElement ------------------------------------+
  /// | +--- rootElement ---------------------+                  |
  /// | |                                     |                  |
  /// | |                                     |    container     |
  /// | |    size applied to *this*           |    must be able  |
  /// | |                                     |    to reflow     |
  /// | |                                     |                  |
  /// | +-------------------------------------+                  |
  /// +----------------------------------------------------------+
  /// <p>More HTML content...</p>
  /// ```
  ///
  /// The `hostElement` needs to be styled in a way that allows its size to flow
  /// with its contents. Things like `max-height: 100px; overflow: hidden` will
  /// work as expected (by hiding the overflowing part of the flutter app), but
  /// if in that case flutter is not made aware of that max-height with
  /// `physicalConstraints`, it will end up rendering more pixels that are visible
  /// on the screen, with a possible hit to performance.
  ///
  /// TL;DR: The `viewConstraints` of a Flutter view, must take into consideration
  /// the CSS box-model restrictions imposed on its `hostElement` (especially when
  /// hiding `overflow`). Flutter does not attempt to interpret the styles of
  /// `hostElement` to compute its `physicalConstraints`, only its current size.
  void resize(ui.Size newPhysicalSize) {
    // The browser uses CSS, and CSS operates in logical sizes.
    final ui.Size logicalSize = newPhysicalSize / devicePixelRatio;
    dom.rootElement.style
      ..width = '${logicalSize.width}px'
      ..height = '${logicalSize.height}px';

    // Force an update of the physicalSize so it's ready for the renderer.
    _computePhysicalSize();
  }

  /// Lazily populated and cleared at the end of the frame.
  ui.Size? _physicalSize;

  ui.Size? debugPhysicalSizeOverride;

  /// Computes the physical size of the view.
  ///
  /// This function is expensive. It triggers browser layout if there are
  /// pending DOM writes.
  ui.Size _computePhysicalSize() {
    ui.Size? physicalSizeOverride;

    assert(() {
      physicalSizeOverride = debugPhysicalSizeOverride;
      return true;
    }());

    return physicalSizeOverride ?? dimensionsProvider.computePhysicalSize();
  }

  /// Forces the view to recompute its physical size. Useful for tests.
  void debugForceResize() {
    _physicalSize = _computePhysicalSize();
  }

  @override
  ViewPadding get viewInsets => _viewInsets;
  ViewPadding _viewInsets = ui.ViewPadding.zero as ViewPadding;

  @override
  ViewPadding get viewPadding => _viewConfiguration.viewPadding;

  @override
  ViewPadding get systemGestureInsets => _viewConfiguration.systemGestureInsets;

  @override
  ViewPadding get padding => _viewConfiguration.padding;

  @override
  ui.GestureSettings get gestureSettings => _viewConfiguration.gestureSettings;

  @override
  List<ui.DisplayFeature> get displayFeatures => _viewConfiguration.displayFeatures;

  @override
  EngineFlutterDisplay get display => EngineFlutterDisplay.instance;

  @override
  double get devicePixelRatio => display.devicePixelRatio;

  @visibleForTesting
  final DimensionsProvider dimensionsProvider;

  Stream<ui.Size?> get onResize => dimensionsProvider.onResize;

  /// Called immediately after the view has been resized.
  ///
  /// When there is a text editing going on in mobile devices, do not change
  /// the physicalSize, change the [window.viewInsets]. See:
  /// https://api.flutter.dev/flutter/dart-ui/FlutterView/viewInsets.html
  /// https://api.flutter.dev/flutter/dart-ui/FlutterView/physicalSize.html
  ///
  /// Note: always check for rotations for a mobile device. Update the physical
  /// size if the change is caused by a rotation.
  void _didResize(ui.Size? newSize) {
    StyleManager.scaleSemanticsHost(dom.semanticsHost, devicePixelRatio);
    final ui.Size newPhysicalSize = _computePhysicalSize();
    final bool isEditingOnMobile =
        isMobile && !_isRotation(newPhysicalSize) && textEditing.isEditing;
    if (isEditingOnMobile) {
      _computeOnScreenKeyboardInsets(true);
    } else {
      _physicalSize = newPhysicalSize;
      // When physical size changes this value has to be recalculated.
      _computeOnScreenKeyboardInsets(false);
    }
    platformDispatcher.invokeOnMetricsChanged();
  }

  /// Uses the previous physical size and current innerHeight/innerWidth
  /// values to decide if a device is rotating.
  ///
  /// During a rotation the height and width values will (almost) swap place.
  /// Values can slightly differ due to space occupied by the browser header.
  /// For example the following values are collected for Pixel 3 rotation:
  ///
  /// height: 658 width: 393
  /// new height: 313 new width: 738
  ///
  /// The following values are from a changed caused by virtual keyboard.
  ///
  /// height: 658 width: 393
  /// height: 368 width: 393
  bool _isRotation(ui.Size newPhysicalSize) {
    // This method compares the new dimensions with the previous ones.
    // Return false if the previous dimensions are not set.
    if (_physicalSize != null) {
      // First confirm both height and width are effected.
      if (_physicalSize!.height != newPhysicalSize.height && _physicalSize!.width != newPhysicalSize.width) {
        // If prior to rotation height is bigger than width it should be the
        // opposite after the rotation and vice versa.
        if ((_physicalSize!.height > _physicalSize!.width && newPhysicalSize.height < newPhysicalSize.width) ||
            (_physicalSize!.width > _physicalSize!.height && newPhysicalSize.width < newPhysicalSize.height)) {
          // Rotation detected
          return true;
        }
      }
    }
    return false;
  }

  void _computeOnScreenKeyboardInsets(bool isEditingOnMobile) {
    _viewInsets = dimensionsProvider.computeKeyboardInsets(
      _physicalSize!.height,
      isEditingOnMobile,
    );
  }
}

final class _EngineFlutterViewImpl extends EngineFlutterView {
  _EngineFlutterViewImpl(
    EnginePlatformDispatcher platformDispatcher,
    DomElement hostElement, {
      JsViewConstraints? viewConstraints,
    }
  ) : super._(_nextViewId++, platformDispatcher, hostElement, viewConstraints: viewConstraints);
}

/// The Web implementation of [ui.SingletonFlutterWindow].
final class EngineFlutterWindow extends EngineFlutterView implements ui.SingletonFlutterWindow {
  EngineFlutterWindow._(
    EnginePlatformDispatcher platformDispatcher,
    DomElement? hostElement,
  ) : super._(kImplicitViewId, platformDispatcher, hostElement) {
    if (ui_web.isCustomUrlStrategySet) {
      _browserHistory = createHistoryForExistingState(ui_web.urlStrategy);
    }
  }

  @override
  void dispose() {
    super.dispose();
    _browserHistory?.dispose();
  }

  @override
  ui.VoidCallback? get onMetricsChanged => platformDispatcher.onMetricsChanged;
  @override
  set onMetricsChanged(ui.VoidCallback? callback) {
    platformDispatcher.onMetricsChanged = callback;
  }

  @override
  ui.Locale get locale => platformDispatcher.locale;
  @override
  List<ui.Locale> get locales => platformDispatcher.locales;

  @override
  ui.Locale? computePlatformResolvedLocale(List<ui.Locale> supportedLocales) {
    return platformDispatcher.computePlatformResolvedLocale(supportedLocales);
  }

  @override
  ui.VoidCallback? get onLocaleChanged => platformDispatcher.onLocaleChanged;
  @override
  set onLocaleChanged(ui.VoidCallback? callback) {
    platformDispatcher.onLocaleChanged = callback;
  }

  @override
  String get initialLifecycleState => platformDispatcher.initialLifecycleState;

  @override
  double get textScaleFactor => platformDispatcher.textScaleFactor;

  @override
  bool get nativeSpellCheckServiceDefined => platformDispatcher.nativeSpellCheckServiceDefined;

  @override
  bool get brieflyShowPassword => platformDispatcher.brieflyShowPassword;

  @override
  bool get alwaysUse24HourFormat => platformDispatcher.alwaysUse24HourFormat;

  @override
  ui.VoidCallback? get onTextScaleFactorChanged => platformDispatcher.onTextScaleFactorChanged;
  @override
  set onTextScaleFactorChanged(ui.VoidCallback? callback) {
    platformDispatcher.onTextScaleFactorChanged = callback;
  }

  @override
  ui.Brightness get platformBrightness => platformDispatcher.platformBrightness;

  @override
  ui.VoidCallback? get onPlatformBrightnessChanged => platformDispatcher.onPlatformBrightnessChanged;
  @override
  set onPlatformBrightnessChanged(ui.VoidCallback? callback) {
    platformDispatcher.onPlatformBrightnessChanged = callback;
  }

  @override
  String? get systemFontFamily => platformDispatcher.systemFontFamily;

  @override
  ui.VoidCallback? get onSystemFontFamilyChanged => platformDispatcher.onSystemFontFamilyChanged;
  @override
  set onSystemFontFamilyChanged(ui.VoidCallback? callback) {
    platformDispatcher.onSystemFontFamilyChanged = callback;
  }

  @override
  ui.FrameCallback? get onBeginFrame => platformDispatcher.onBeginFrame;
  @override
  set onBeginFrame(ui.FrameCallback? callback) {
    platformDispatcher.onBeginFrame = callback;
  }

  @override
  ui.VoidCallback? get onDrawFrame => platformDispatcher.onDrawFrame;
  @override
  set onDrawFrame(ui.VoidCallback? callback) {
    platformDispatcher.onDrawFrame = callback;
  }

  @override
  ui.TimingsCallback? get onReportTimings => platformDispatcher.onReportTimings;
  @override
  set onReportTimings(ui.TimingsCallback? callback) {
    platformDispatcher.onReportTimings = callback;
  }

  @override
  ui.PointerDataPacketCallback? get onPointerDataPacket => platformDispatcher.onPointerDataPacket;
  @override
  set onPointerDataPacket(ui.PointerDataPacketCallback? callback) {
    platformDispatcher.onPointerDataPacket = callback;
  }

  @override
  ui.KeyDataCallback? get onKeyData => platformDispatcher.onKeyData;
  @override
  set onKeyData(ui.KeyDataCallback? callback) {
    platformDispatcher.onKeyData = callback;
  }

  @override
  String get defaultRouteName => platformDispatcher.defaultRouteName;

  @override
  void scheduleFrame() => platformDispatcher.scheduleFrame();

  @override
  bool get semanticsEnabled => platformDispatcher.semanticsEnabled;

  @override
  ui.VoidCallback? get onSemanticsEnabledChanged => platformDispatcher.onSemanticsEnabledChanged;
  @override
  set onSemanticsEnabledChanged(ui.VoidCallback? callback) {
    platformDispatcher.onSemanticsEnabledChanged = callback;
  }

  @override
  ui.FrameData get frameData => const ui.FrameData.webOnly();

  @override
  ui.VoidCallback? get onFrameDataChanged => null;
  @override
  set onFrameDataChanged(ui.VoidCallback? callback) {}

  @override
  ui.AccessibilityFeatures get accessibilityFeatures => platformDispatcher.accessibilityFeatures;

  @override
  ui.VoidCallback? get onAccessibilityFeaturesChanged =>
      platformDispatcher.onAccessibilityFeaturesChanged;
  @override
  set onAccessibilityFeaturesChanged(ui.VoidCallback? callback) {
    platformDispatcher.onAccessibilityFeaturesChanged = callback;
  }

  @override
  void sendPlatformMessage(
    String name,
    ByteData? data,
    ui.PlatformMessageResponseCallback? callback,
  ) {
    platformDispatcher.sendPlatformMessage(name, data, callback);
  }

  @override
  ui.PlatformMessageCallback? get onPlatformMessage => platformDispatcher.onPlatformMessage;
  @override
  set onPlatformMessage(ui.PlatformMessageCallback? callback) {
    platformDispatcher.onPlatformMessage = callback;
  }

  @override
  void setIsolateDebugName(String name) => ui.PlatformDispatcher.instance.setIsolateDebugName(name);

  /// Handles the browser history integration to allow users to use the back
  /// button, etc.
  BrowserHistory get browserHistory {
    return _browserHistory ??=
        createHistoryForExistingState(_urlStrategyForInitialization);
  }

  ui_web.UrlStrategy? get _urlStrategyForInitialization {
    // Prevent any further customization of URL strategy.
    ui_web.preventCustomUrlStrategy();
    return ui_web.urlStrategy;
  }

  BrowserHistory?
      _browserHistory; // Must be either SingleEntryBrowserHistory or MultiEntriesBrowserHistory.

  Future<void> _useSingleEntryBrowserHistory() async {
    // Recreate the browser history mode that's appropriate for the existing
    // history state.
    //
    // If it happens to be a single-entry one, then there's nothing further to do.
    //
    // But if it's a multi-entry one, it will be torn down below and replaced
    // with a single-entry history.
    //
    // See: https://github.com/flutter/flutter/issues/79241
    _browserHistory ??=
        createHistoryForExistingState(_urlStrategyForInitialization);

    if (_browserHistory is SingleEntryBrowserHistory) {
      return;
    }

    // At this point, we know that `_browserHistory` is a non-null
    // `MultiEntriesBrowserHistory` instance.
    final ui_web.UrlStrategy? strategy = _browserHistory?.urlStrategy;
    await _browserHistory?.tearDown();
    _browserHistory = SingleEntryBrowserHistory(urlStrategy: strategy);
  }

  Future<void> _useMultiEntryBrowserHistory() async {
    // Recreate the browser history mode that's appropriate for the existing
    // history state.
    //
    // If it happens to be a multi-entry one, then there's nothing further to do.
    //
    // But if it's a single-entry one, it will be torn down below and replaced
    // with a multi-entry history.
    //
    // See: https://github.com/flutter/flutter/issues/79241
    _browserHistory ??=
        createHistoryForExistingState(_urlStrategyForInitialization);

    if (_browserHistory is MultiEntriesBrowserHistory) {
      return;
    }

    // At this point, we know that `_browserHistory` is a non-null
    // `SingleEntryBrowserHistory` instance.
    final ui_web.UrlStrategy? strategy = _browserHistory?.urlStrategy;
    await _browserHistory?.tearDown();
    _browserHistory = MultiEntriesBrowserHistory(urlStrategy: strategy);
  }

  @visibleForTesting
  Future<void> debugInitializeHistory(
    ui_web.UrlStrategy? strategy, {
    required bool useSingle,
  }) async {
    await _browserHistory?.tearDown();

    ui_web.urlStrategy = strategy;
    if (useSingle) {
      _browserHistory = SingleEntryBrowserHistory(urlStrategy: strategy);
    } else {
      _browserHistory = MultiEntriesBrowserHistory(urlStrategy: strategy);
    }
  }

  Future<void> resetHistory() async {
    await _browserHistory?.tearDown();
    _browserHistory = null;
    ui_web.debugResetCustomUrlStrategy();
  }

  Future<void> _endOfTheLine = Future<void>.value();

  Future<bool> _waitInTheLine(_HandleMessageCallBack callback) async {
    final Future<void> currentPosition = _endOfTheLine;
    final Completer<void> completer = Completer<void>();
    _endOfTheLine = completer.future;
    await currentPosition;
    bool result = false;
    try {
      result = await callback();
    } finally {
      completer.complete();
    }
    return result;
  }

  Future<bool> handleNavigationMessage(ByteData? data) async {
    return _waitInTheLine(() async {
      final MethodCall decoded = const JSONMethodCodec().decodeMethodCall(data);
      final Map<String, dynamic>? arguments = decoded.arguments as Map<String, dynamic>?;
      switch (decoded.method) {
        case 'selectMultiEntryHistory':
          await _useMultiEntryBrowserHistory();
          return true;
        case 'selectSingleEntryHistory':
          await _useSingleEntryBrowserHistory();
          return true;
        // the following cases assert that arguments are not null
        case 'routeUpdated': // deprecated
          assert(arguments != null);
          await _useSingleEntryBrowserHistory();
          browserHistory.setRouteName(arguments!.tryString('routeName'));
          return true;
        case 'routeInformationUpdated':
          assert(arguments != null);
          final String? uriString = arguments!.tryString('uri');
          final String path;
          if (uriString != null) {
            final Uri uri = Uri.parse(uriString);
            // Need to remove scheme and authority.
            path = Uri.decodeComponent(
              Uri(
                path: uri.path.isEmpty ? '/' : uri.path,
                queryParameters: uri.queryParametersAll.isEmpty ? null : uri.queryParametersAll,
                fragment: uri.fragment.isEmpty ? null : uri.fragment,
              ).toString(),
            );
          } else {
            path = arguments.tryString('location')!;
          }
          browserHistory.setRouteName(
            path,
            state: arguments['state'],
            replace: arguments.tryBool('replace') ?? false,
          );
          return true;
      }
      return false;
    });
  }

  // TODO(mdebbar): Deprecate this and remove it.
  // https://github.com/flutter/flutter/issues/127395
  void debugOverrideDevicePixelRatio(double? value) {
    assert(() {
      printWarning(
        'The window.debugOverrideDevicePixelRatio API is deprecated and will '
        'be removed in a future release. Please use '
        '`debugOverrideDevicePixelRatio` from `dart:ui_web` instead.',
      );
      return true;
    }());
    display.debugOverrideDevicePixelRatio(value);
  }

  // TODO(mdebbar): Deprecate this and remove it.
  // https://github.com/flutter/flutter/issues/127395
  ui.Size? get webOnlyDebugPhysicalSizeOverride {
    assert(() {
      printWarning(
        'The webOnlyDebugPhysicalSizeOverride API is deprecated and will be '
        'removed in a future release. Please use '
        '`SingletonFlutterWindow.debugPhysicalSizeOverride` from `dart:ui_web` '
        'instead.',
      );
      return true;
    }());
    return debugPhysicalSizeOverride;
  }

  // TODO(mdebbar): Deprecate this and remove it.
  // https://github.com/flutter/flutter/issues/127395
  set webOnlyDebugPhysicalSizeOverride(ui.Size? value) {
    assert(() {
      printWarning(
        'The webOnlyDebugPhysicalSizeOverride API is deprecated and will be '
        'removed in a future release. Please use '
        '`SingletonFlutterWindow.debugPhysicalSizeOverride` from `dart:ui_web` '
        'instead.',
      );
      return true;
    }());
    debugPhysicalSizeOverride = value;
  }
}

/// The window singleton.
///
/// `dart:ui` window delegates to this value. However, this value has a wider
/// API surface, providing Web-specific functionality that the standard
/// `dart:ui` version does not.
EngineFlutterWindow get window {
  assert(
    _window != null,
    'Trying to access the implicit FlutterView, but it is not available.\n'
    'Note: the implicit FlutterView is not available in multi-view mode.',
  );
  return _window!;
}
EngineFlutterWindow? _window;

/// Initializes the [window] (aka the implicit view), if it's not already
/// initialized.
EngineFlutterWindow ensureImplicitViewInitialized({
  DomElement? hostElement,
}) {
  if (_window == null) {
    _window = EngineFlutterView.implicit(
      EnginePlatformDispatcher.instance,
      hostElement,
    );
    EnginePlatformDispatcher.instance.viewManager.registerView(_window!);
  }
  return _window!;
}

/// The Web implementation of [ui.ViewPadding].
class ViewPadding implements ui.ViewPadding {
  const ViewPadding({
    required this.left,
    required this.top,
    required this.right,
    required this.bottom,
  });

  @override
  final double left;
  @override
  final double top;
  @override
  final double right;
  @override
  final double bottom;
}

class ViewConstraints implements ui.ViewConstraints {
  const ViewConstraints({
    this.minWidth = 0.0,
    this.maxWidth = double.infinity,
    this.minHeight = 0.0,
    this.maxHeight = double.infinity,
  });

  ViewConstraints.tight(ui.Size size)
    : minWidth = size.width,
      maxWidth = size.width,
      minHeight = size.height,
      maxHeight = size.height;

  /// Converts JsViewConstraints into ViewConstraints.
  ///
  /// Since JsViewConstraints are expressed by the user, in logical pixels, this
  /// conversion uses logical pixels for the current size as well.
  ///
  /// The resulting ViewConstraints object will be multiplied by devicePixelRatio
  /// later to compute the physicalViewConstraints, which is what the framework
  /// uses.
  factory ViewConstraints.fromJs(
    JsViewConstraints? constraints, ui.Size currentLogicalSize) {
    if (constraints == null) {
      return ViewConstraints.tight(currentLogicalSize);
    }
    return ViewConstraints(
      minWidth: _computeMinConstraintValue(constraints.minWidth, currentLogicalSize.width),
      minHeight: _computeMinConstraintValue(constraints.minHeight, currentLogicalSize.height),
      maxWidth: _computeMaxConstraintValue(constraints.maxWidth, currentLogicalSize.width),
      maxHeight: _computeMaxConstraintValue(constraints.maxHeight, currentLogicalSize.height),
    );
  }

  @override
  final double minWidth;
  @override
  final double maxWidth;
  @override
  final double minHeight;
  @override
  final double maxHeight;

  @override
  bool isSatisfiedBy(ui.Size size) {
    return (minWidth <= size.width) && (size.width <= maxWidth) &&
           (minHeight <= size.height) && (size.height <= maxHeight);
  }

  @override
  bool get isTight => minWidth >= maxWidth && minHeight >= maxHeight;

  ViewConstraints operator*(double factor) {
    return ViewConstraints(
      minWidth: minWidth * factor,
      maxWidth: maxWidth * factor,
      minHeight: minHeight * factor,
      maxHeight: maxHeight * factor,
    );
  }

  @override
  ViewConstraints operator/(double factor) {
    return ViewConstraints(
      minWidth: minWidth / factor,
      maxWidth: maxWidth / factor,
      minHeight: minHeight / factor,
      maxHeight: maxHeight / factor,
    );
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is ViewConstraints
        && other.minWidth == minWidth
        && other.maxWidth == maxWidth
        && other.minHeight == minHeight
        && other.maxHeight == maxHeight;
  }

  @override
  int get hashCode => Object.hash(minWidth, maxWidth, minHeight, maxHeight);

  @override
  String toString() {
    if (minWidth == double.infinity && minHeight == double.infinity) {
      return 'ViewConstraints(biggest)';
    }
    if (minWidth == 0 && maxWidth == double.infinity &&
        minHeight == 0 && maxHeight == double.infinity) {
      return 'ViewConstraints(unconstrained)';
    }
    String describe(double min, double max, String dim) {
      if (min == max) {
        return '$dim=${min.toStringAsFixed(1)}';
      }
      return '${min.toStringAsFixed(1)}<=$dim<=${max.toStringAsFixed(1)}';
    }
    final String width = describe(minWidth, maxWidth, 'w');
    final String height = describe(minHeight, maxHeight, 'h');
    return 'ViewConstraints($width, $height)';
  }
}

// Computes the "min" value for a constraint that takes into account user `desired`
// configuration and the actual available value.
//
// Returns the `desired` value unless it is `null`, in which case it returns the
// `available` value.
double _computeMinConstraintValue(double? desired, double available) {
  assert(desired == null || desired >= 0, 'Minimum constraint must be >= 0 if set.');
  assert(desired == null || desired.isFinite, 'Minimum constraint must be finite.');
  return desired ?? available;
}

// Computes the "max" value for a constraint that takes into account user `desired`
// configuration and the `available` size.
//
// Returns the `desired` value unless it is `null`, in which case it returns the
// `available` value.
//
// A `desired` value of `Infinity` or `Number.POSITIVE_INFINITY` (from JS) means
// "unconstrained".
//
// This method allows returning values larger than `available`, so the Flutter
// app is able to stretch its container up to a certain value, without being
// fully unconstrained.
double _computeMaxConstraintValue(double? desired, double available) {
  assert(desired == null || desired >= 0, 'Maximum constraint must be >= 0 if set.');
  return desired ?? available;
}
