// 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:ui' hide window;

import 'package:flutter/foundation.dart';

/// Test version of [AccessibilityFeatures] in which specific features may
/// be set to arbitrary values.
///
/// By default, all features are disabled. For an instance where all the
/// features are enabled, consider the [FakeAccessibilityFeatures.allOn]
/// constant.
@immutable
class FakeAccessibilityFeatures implements AccessibilityFeatures {
  /// Creates a test instance of [AccessibilityFeatures].
  ///
  /// By default, all features are disabled.
  const FakeAccessibilityFeatures({
    this.accessibleNavigation = false,
    this.invertColors = false,
    this.disableAnimations = false,
    this.boldText = false,
    this.reduceMotion = false,
    this.highContrast = false,
    this.onOffSwitchLabels = false,
  });

  /// An instance of [AccessibilityFeatures] where all the features are enabled.
  static const FakeAccessibilityFeatures allOn = FakeAccessibilityFeatures(
    accessibleNavigation: true,
    invertColors: true,
    disableAnimations: true,
    boldText: true,
    reduceMotion: true,
    highContrast: true,
    onOffSwitchLabels: true,
  );

  @override
  final bool accessibleNavigation;

  @override
  final bool invertColors;

  @override
  final bool disableAnimations;

  @override
  final bool boldText;

  @override
  final bool reduceMotion;

  @override
  final bool highContrast;

  @override
  final bool onOffSwitchLabels;

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is FakeAccessibilityFeatures
        && other.accessibleNavigation == accessibleNavigation
        && other.invertColors == invertColors
        && other.disableAnimations == disableAnimations
        && other.boldText == boldText
        && other.reduceMotion == reduceMotion
        && other.highContrast == highContrast
        && other.onOffSwitchLabels == onOffSwitchLabels;
  }

  @override
  int get hashCode {
    return Object.hash(
      accessibleNavigation,
      invertColors,
      disableAnimations,
      boldText,
      reduceMotion,
      highContrast,
      onOffSwitchLabels,
    );
  }

  /// This gives us some grace time when the dart:ui side adds something to
  /// [AccessibilityFeatures], and makes things easier when we do rolls to
  /// give us time to catch up.
  ///
  /// If you would like to add to this class, changes must first be made in the
  /// engine, followed by the framework.
  @override
  dynamic noSuchMethod(Invocation invocation) {
    return null;
  }
}

/// Used to fake insets and padding for [TestFlutterView]s.
///
/// See also:
///
///   * [TestFlutterView.padding], [TestFlutterView.systemGestureInsets],
///     [TestFlutterView.viewInsets], and [TestFlutterView.viewPadding] for test
///     properties that make use of [FakeViewPadding].
@immutable
class FakeViewPadding implements ViewPadding {
  /// Instantiates a new [FakeViewPadding] object for faking insets and padding
  /// during tests.
  const FakeViewPadding({
    this.left = 0.0,
    this.top = 0.0,
    this.right = 0.0,
    this.bottom = 0.0,
  });

  FakeViewPadding._wrap(ViewPadding base) :
    left = base.left,
    top = base.top,
    right = base.right,
    bottom = base.bottom;

  /// A view padding that has zeros for each edge.
  static const FakeViewPadding zero = FakeViewPadding();

  @override
  final double left;

  @override
  final double top;

  @override
  final double right;

  @override
  final double bottom;
}

/// [PlatformDispatcher] that wraps another [PlatformDispatcher] and
/// allows faking of some properties for testing purposes.
///
/// See also:
///
///   * [TestFlutterView], which wraps a [FlutterView] for testing and
///     mocking purposes.
class TestPlatformDispatcher implements PlatformDispatcher {
  /// Constructs a [TestPlatformDispatcher] that defers all behavior to the given
  /// [PlatformDispatcher] unless explicitly overridden for test purposes.
  TestPlatformDispatcher({
    required PlatformDispatcher platformDispatcher,
  }) : _platformDispatcher = platformDispatcher {
    _updateViewsAndDisplays();
    _platformDispatcher.onMetricsChanged = _handleMetricsChanged;
  }

  /// The [PlatformDispatcher] that is wrapped by this [TestPlatformDispatcher].
  final PlatformDispatcher _platformDispatcher;

  @override
  TestFlutterView? get implicitView {
    return _platformDispatcher.implicitView != null
      ? _testViews[_platformDispatcher.implicitView!.viewId]!
      : null;
  }

  final Map<int, TestFlutterView> _testViews = <int, TestFlutterView>{};
  final Map<int, TestDisplay> _testDisplays = <int, TestDisplay>{};

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

  void _handleMetricsChanged() {
    _updateViewsAndDisplays();
    _onMetricsChanged?.call();
  }

  @override
  Locale get locale => _localeTestValue ?? _platformDispatcher.locale;
  Locale? _localeTestValue;
  /// Hides the real locale and reports the given [localeTestValue] instead.
  set localeTestValue(Locale localeTestValue) { // ignore: avoid_setters_without_getters
    _localeTestValue = localeTestValue;
    onLocaleChanged?.call();
  }

  /// Deletes any existing test locale and returns to using the real locale.
  void clearLocaleTestValue() {
    _localeTestValue = null;
    onLocaleChanged?.call();
  }

  @override
  List<Locale> get locales => _localesTestValue ?? _platformDispatcher.locales;
  List<Locale>? _localesTestValue;
  /// Hides the real locales and reports the given [localesTestValue] instead.
  set localesTestValue(List<Locale> localesTestValue) { // ignore: avoid_setters_without_getters
    _localesTestValue = localesTestValue;
    onLocaleChanged?.call();
  }

  /// Deletes any existing test locales and returns to using the real locales.
  void clearLocalesTestValue() {
    _localesTestValue = null;
    onLocaleChanged?.call();
  }

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

  @override
  String get initialLifecycleState => _initialLifecycleStateTestValue;
  String _initialLifecycleStateTestValue = '';
  /// Sets a faked initialLifecycleState for testing.
  set initialLifecycleStateTestValue(String state) { // ignore: avoid_setters_without_getters
    _initialLifecycleStateTestValue = state;
  }

  /// Resets [initialLifecycleState] to the default value for the platform.
  void resetInitialLifecycleState() {
    _initialLifecycleStateTestValue = '';
  }

  @override
  double get textScaleFactor => _textScaleFactorTestValue ?? _platformDispatcher.textScaleFactor;
  double? _textScaleFactorTestValue;
  /// Hides the real text scale factor and reports the given
  /// [textScaleFactorTestValue] instead.
  set textScaleFactorTestValue(double textScaleFactorTestValue) { // ignore: avoid_setters_without_getters
    _textScaleFactorTestValue = textScaleFactorTestValue;
    onTextScaleFactorChanged?.call();
  }

  /// Deletes any existing test text scale factor and returns to using the real
  /// text scale factor.
  void clearTextScaleFactorTestValue() {
    _textScaleFactorTestValue = null;
    onTextScaleFactorChanged?.call();
  }

  @override
  Brightness get platformBrightness => _platformBrightnessTestValue ?? _platformDispatcher.platformBrightness;
  Brightness? _platformBrightnessTestValue;
  @override
  VoidCallback? get onPlatformBrightnessChanged => _platformDispatcher.onPlatformBrightnessChanged;
  @override
  set onPlatformBrightnessChanged(VoidCallback? callback) {
    _platformDispatcher.onPlatformBrightnessChanged = callback;
  }
  /// Hides the real platform brightness and reports the given
  /// [platformBrightnessTestValue] instead.
  set platformBrightnessTestValue(Brightness platformBrightnessTestValue) { // ignore: avoid_setters_without_getters
    _platformBrightnessTestValue = platformBrightnessTestValue;
    onPlatformBrightnessChanged?.call();
  }

  /// Deletes any existing test platform brightness and returns to using the
  /// real platform brightness.
  void clearPlatformBrightnessTestValue() {
    _platformBrightnessTestValue = null;
    onPlatformBrightnessChanged?.call();
  }

  @override
  bool get alwaysUse24HourFormat => _alwaysUse24HourFormatTestValue ?? _platformDispatcher.alwaysUse24HourFormat;
  bool? _alwaysUse24HourFormatTestValue;
  /// Hides the real clock format and reports the given
  /// [alwaysUse24HourFormatTestValue] instead.
  set alwaysUse24HourFormatTestValue(bool alwaysUse24HourFormatTestValue) { // ignore: avoid_setters_without_getters
    _alwaysUse24HourFormatTestValue = alwaysUse24HourFormatTestValue;
  }

  /// Deletes any existing test clock format and returns to using the real clock
  /// format.
  void clearAlwaysUse24HourTestValue() {
    _alwaysUse24HourFormatTestValue = null;
  }

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

  @override
  bool get nativeSpellCheckServiceDefined => _nativeSpellCheckServiceDefinedTestValue ?? _platformDispatcher.nativeSpellCheckServiceDefined;
  bool? _nativeSpellCheckServiceDefinedTestValue;
  set nativeSpellCheckServiceDefinedTestValue(bool nativeSpellCheckServiceDefinedTestValue) { // ignore: avoid_setters_without_getters
    _nativeSpellCheckServiceDefinedTestValue = nativeSpellCheckServiceDefinedTestValue;
  }

  /// Deletes existing value that determines whether or not a native spell check
  /// service is defined and returns to the real value.
  void clearNativeSpellCheckServiceDefined() {
    _nativeSpellCheckServiceDefinedTestValue = null;
  }

  @override
  bool get brieflyShowPassword => _brieflyShowPasswordTestValue ?? _platformDispatcher.brieflyShowPassword;
  bool? _brieflyShowPasswordTestValue;
  /// Hides the real [brieflyShowPassword] and reports the given
  /// `brieflyShowPasswordTestValue` instead.
  set brieflyShowPasswordTestValue(bool brieflyShowPasswordTestValue) { // ignore: avoid_setters_without_getters
    _brieflyShowPasswordTestValue = brieflyShowPasswordTestValue;
  }

  /// Resets [brieflyShowPassword] to the default value for the platform.
  void resetBrieflyShowPassword() {
    _brieflyShowPasswordTestValue = null;
  }

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

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

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

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

  @override
  String get defaultRouteName => _defaultRouteNameTestValue ?? _platformDispatcher.defaultRouteName;
  String? _defaultRouteNameTestValue;
  /// Hides the real default route name and reports the given
  /// [defaultRouteNameTestValue] instead.
  set defaultRouteNameTestValue(String defaultRouteNameTestValue) { // ignore: avoid_setters_without_getters
    _defaultRouteNameTestValue = defaultRouteNameTestValue;
  }

  /// Deletes any existing test default route name and returns to using the real
  /// default route name.
  void clearDefaultRouteNameTestValue() {
    _defaultRouteNameTestValue = null;
  }

  @override
  void scheduleFrame() {
    _platformDispatcher.scheduleFrame();
  }

  @override
  bool get semanticsEnabled => _semanticsEnabledTestValue ?? _platformDispatcher.semanticsEnabled;
  bool? _semanticsEnabledTestValue;
  /// Hides the real semantics enabled and reports the given
  /// [semanticsEnabledTestValue] instead.
  set semanticsEnabledTestValue(bool semanticsEnabledTestValue) { // ignore: avoid_setters_without_getters
    _semanticsEnabledTestValue = semanticsEnabledTestValue;
    onSemanticsEnabledChanged?.call();
  }

  /// Deletes any existing test semantics enabled and returns to using the real
  /// semantics enabled.
  void clearSemanticsEnabledTestValue() {
    _semanticsEnabledTestValue = null;
    onSemanticsEnabledChanged?.call();
  }

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

  @override
  SemanticsActionEventCallback? get onSemanticsActionEvent => _platformDispatcher.onSemanticsActionEvent;
  @override
  set onSemanticsActionEvent(SemanticsActionEventCallback? callback) {
    _platformDispatcher.onSemanticsActionEvent = callback;
  }

  @override
  AccessibilityFeatures get accessibilityFeatures => _accessibilityFeaturesTestValue ?? _platformDispatcher.accessibilityFeatures;
  AccessibilityFeatures? _accessibilityFeaturesTestValue;
  /// Hides the real accessibility features and reports the given
  /// [accessibilityFeaturesTestValue] instead.
  ///
  /// Consider using [FakeAccessibilityFeatures] to provide specific
  /// values for the various accessibility features under test.
  set accessibilityFeaturesTestValue(AccessibilityFeatures accessibilityFeaturesTestValue) { // ignore: avoid_setters_without_getters
    _accessibilityFeaturesTestValue = accessibilityFeaturesTestValue;
    onAccessibilityFeaturesChanged?.call();
  }

  /// Deletes any existing test accessibility features and returns to using the
  /// real accessibility features.
  void clearAccessibilityFeaturesTestValue() {
    _accessibilityFeaturesTestValue = null;
    onAccessibilityFeaturesChanged?.call();
  }

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

  @override
  void setIsolateDebugName(String name) {
    _platformDispatcher.setIsolateDebugName(name);
  }

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

  /// Delete any test value properties that have been set on this [TestPlatformDispatcher]
  /// and return to reporting the real [PlatformDispatcher] values for all
  /// [PlatformDispatcher] properties.
  ///
  /// If desired, clearing of properties can be done on an individual basis,
  /// e.g., [clearLocaleTestValue].
  void clearAllTestValues() {
    clearAccessibilityFeaturesTestValue();
    clearAlwaysUse24HourTestValue();
    clearDefaultRouteNameTestValue();
    clearPlatformBrightnessTestValue();
    clearLocaleTestValue();
    clearLocalesTestValue();
    clearSemanticsEnabledTestValue();
    clearTextScaleFactorTestValue();
    clearNativeSpellCheckServiceDefined();
    resetBrieflyShowPassword();
    resetInitialLifecycleState();
    resetSystemFontFamily();
  }

  @override
  VoidCallback? get onFrameDataChanged => _platformDispatcher.onFrameDataChanged;
  @override
  set onFrameDataChanged(VoidCallback? value) {
    _platformDispatcher.onFrameDataChanged = value;
  }

  @override
  KeyDataCallback? get onKeyData => _platformDispatcher.onKeyData;

  @override
  set onKeyData(KeyDataCallback? onKeyData) {
    _platformDispatcher.onKeyData = onKeyData;
  }

  @override
  VoidCallback? get onPlatformConfigurationChanged => _platformDispatcher.onPlatformConfigurationChanged;

  @override
  set onPlatformConfigurationChanged(VoidCallback? onPlatformConfigurationChanged) {
    _platformDispatcher.onPlatformConfigurationChanged = onPlatformConfigurationChanged;
  }

  @override
  Locale? computePlatformResolvedLocale(List<Locale> supportedLocales) => _platformDispatcher.computePlatformResolvedLocale(supportedLocales);

  @override
  ByteData? getPersistentIsolateData() => _platformDispatcher.getPersistentIsolateData();

  @override
  Iterable<TestFlutterView> get views => _testViews.values;

  @override
  FlutterView? view({required int id}) => _testViews[id];

  @override
  Iterable<TestDisplay> get displays => _testDisplays.values;

  void _updateViewsAndDisplays() {
    final List<Object> extraDisplayKeys = <Object>[..._testDisplays.keys];
    for (final Display display in _platformDispatcher.displays) {
      extraDisplayKeys.remove(display.id);
      if (!_testDisplays.containsKey(display.id)) {
        _testDisplays[display.id] = TestDisplay(this, display);
      }
    }
    extraDisplayKeys.forEach(_testDisplays.remove);

    final List<Object> extraViewKeys = <Object>[..._testViews.keys];
    for (final FlutterView view in _platformDispatcher.views) {
      // TODO(pdblasi-google): Remove this try-catch once the Display API is stable and supported on all platforms
      late final TestDisplay display;
      try {
        final Display realDisplay = view.display;
        if (_testDisplays.containsKey(realDisplay.id)) {
          display = _testDisplays[view.display.id]!;
        } else {
          display = _UnsupportedDisplay(
            this,
            view,
            'PlatformDispatcher did not contain a Display with id ${realDisplay.id}, '
            'which was expected by FlutterView ($view)',
          );
        }
      } catch (error){
        display = _UnsupportedDisplay(this, view, error);
      }

      extraViewKeys.remove(view.viewId);
      if (!_testViews.containsKey(view.viewId)) {
        _testViews[view.viewId] = TestFlutterView(
          view: view,
          platformDispatcher: this,
          display: display,
        );
      }
    }

    extraViewKeys.forEach(_testViews.remove);
  }

  @override
  ErrorCallback? get onError => _platformDispatcher.onError;
  @override
  set onError(ErrorCallback? value) {
    _platformDispatcher.onError;
  }

  @override
  VoidCallback? get onSystemFontFamilyChanged => _platformDispatcher.onSystemFontFamilyChanged;
  @override
  set onSystemFontFamilyChanged(VoidCallback? value) {
    _platformDispatcher.onSystemFontFamilyChanged = value;
  }

  @override
  FrameData get frameData => _platformDispatcher.frameData;

  @override
  void registerBackgroundIsolate(RootIsolateToken token) {
    _platformDispatcher.registerBackgroundIsolate(token);
  }

  @override
  void requestDartPerformanceMode(DartPerformanceMode mode) {
    _platformDispatcher.requestDartPerformanceMode(mode);
  }

  /// The system font family to use for this test.
  ///
  /// Defaults to the value provided by [PlatformDispatcher.systemFontFamily].
  /// This can only be set in a test environment to emulate different platform
  /// configurations. A standard [PlatformDispatcher] is not mutable from the
  /// framework.
  ///
  /// Setting this value to `null` will force [systemFontFamily] to return
  /// `null`. If you want to have the value default to the platform
  /// [systemFontFamily], use [resetSystemFontFamily].
  ///
  /// See also:
  ///
  ///   * [PlatformDispatcher.systemFontFamily] for the standard implementation
  ///   * [resetSystemFontFamily] to reset this value specifically
  ///   * [clearAllTestValues] to reset all test values for this view
  @override
  String? get systemFontFamily {
    return _forceSystemFontFamilyToBeNull
      ? null
      : _systemFontFamily ?? _platformDispatcher.systemFontFamily;
  }
  String? _systemFontFamily;
  bool _forceSystemFontFamilyToBeNull = false;
  set systemFontFamily(String? value) {
    _systemFontFamily = value;
    if (value == null) {
      _forceSystemFontFamilyToBeNull = true;
    }
    onSystemFontFamilyChanged?.call();
  }

  /// Resets [systemFontFamily] to the default for the platform.
  void resetSystemFontFamily() {
    _systemFontFamily = null;
    _forceSystemFontFamilyToBeNull = false;
    onSystemFontFamilyChanged?.call();
  }

  @override
  void updateSemantics(SemanticsUpdate update) {
    _platformDispatcher.updateSemantics(update);
  }

  /// This gives us some grace time when the dart:ui side adds something to
  /// [PlatformDispatcher], and makes things easier when we do rolls to give
  /// us time to catch up.
  @override
  dynamic noSuchMethod(Invocation invocation) {
    return null;
  }
}

/// A [FlutterView] that wraps another [FlutterView] and allows faking of
/// some properties for testing purposes.
///
/// This class should not be instantiated manually, as
/// it requires a backing [FlutterView] that must be produced from
/// a [PlatformDispatcher].
///
/// See also:
///
///   * [WidgetTester.view] which allows for accessing the [TestFlutterView]
///     for single view applications or widget testing.
///   * [WidgetTester.viewOf] which allows for accessing the appropriate
///     [TestFlutterView] in a given situation for multi-view applications.
///   * [TestPlatformDispatcher], which allows for faking of platform specific
///     functionality.
class TestFlutterView implements FlutterView {
  /// Constructs a [TestFlutterView] that defers all behavior to the given
  /// [FlutterView] unless explicitly overridden for testing.
  TestFlutterView({
    required FlutterView view,
    required TestPlatformDispatcher platformDispatcher,
    required TestDisplay display,
  }) :
    _view = view,
    _platformDispatcher = platformDispatcher,
    _display = display;

  /// The [FlutterView] backing this [TestFlutterView].
  final FlutterView _view;

  @override
  TestPlatformDispatcher get platformDispatcher => _platformDispatcher;
  final TestPlatformDispatcher _platformDispatcher;

  @override
  TestDisplay get display => _display;
  final TestDisplay _display;

  @override
  int get viewId => _view.viewId;

  /// The device pixel ratio to use for this test.
  ///
  /// Defaults to the value provided by [FlutterView.devicePixelRatio]. This
  /// can only be set in a test environment to emulate different view
  /// configurations. A standard [FlutterView] is not mutable from the framework.
  ///
  /// See also:
  ///
  ///   * [FlutterView.devicePixelRatio] for the standard implementation
  ///   * [TestDisplay.devicePixelRatio] which will stay in sync with this value
  ///   * [resetDevicePixelRatio] to reset this value specifically
  ///   * [reset] to reset all test values for this view
  @override
  double get devicePixelRatio => _display._devicePixelRatio ?? _view.devicePixelRatio;
  set devicePixelRatio(double value) {
    _display.devicePixelRatio = value;
  }

  /// Resets [devicePixelRatio] for this test view to the default value for this view.
  ///
  /// This will also reset the [devicePixelRatio] for the [TestDisplay]
  /// that is related to this view.
  void resetDevicePixelRatio() {
    _display.resetDevicePixelRatio();
  }

  /// The display features to use for this test.
  ///
  /// Defaults to the value provided by [FlutterView.displayFeatures]. This
  /// can only be set in a test environment to emulate different view
  /// configurations. A standard [FlutterView] is not mutable from the framework.
  ///
  /// See also:
  ///
  ///   * [FlutterView.displayFeatures] for the standard implementation
  ///   * [resetDisplayFeatures] to reset this value specifically
  ///   * [reset] to reset all test values for this view
  @override
  List<DisplayFeature> get displayFeatures => _displayFeatures ?? _view.displayFeatures;
  List<DisplayFeature>? _displayFeatures;
  set displayFeatures(List<DisplayFeature> value) {
    _displayFeatures = value;
    platformDispatcher.onMetricsChanged?.call();
  }

  /// Resets [displayFeatures] to the default values for this view.
  void resetDisplayFeatures() {
    _displayFeatures = null;
    platformDispatcher.onMetricsChanged?.call();
  }

  /// The padding to use for this test.
  ///
  /// Defaults to the value provided by [FlutterView.padding]. This
  /// can only be set in a test environment to emulate different view
  /// configurations. A standard [FlutterView] is not mutable from the framework.
  ///
  /// See also:
  ///
  ///   * [FakeViewPadding] which is used to set this value for testing
  ///   * [FlutterView.padding] for the standard implementation.
  ///   * [resetPadding] to reset this value specifically.
  ///   * [reset] to reset all test values for this view.
  @override
  FakeViewPadding get padding => _padding ?? FakeViewPadding._wrap(_view.padding);
  FakeViewPadding? _padding;
  set padding(FakeViewPadding value) {
    _padding = value;
    platformDispatcher.onMetricsChanged?.call();
  }

  /// Resets [padding] to the default value for this view.
  void resetPadding() {
    _padding = null;
    platformDispatcher.onMetricsChanged?.call();
  }

  /// The physical size to use for this test.
  ///
  /// Defaults to the value provided by [FlutterView.physicalSize]. This
  /// can only be set in a test environment to emulate different view
  /// configurations. A standard [FlutterView] is not mutable from the framework.
  ///
  /// Setting this value also sets [physicalConstraints] to tight constraints
  /// based on the given size.
  ///
  /// See also:
  ///
  ///   * [FlutterView.physicalSize] for the standard implementation
  ///   * [resetPhysicalSize] to reset this value specifically
  ///   * [reset] to reset all test values for this view
  @override
  Size get physicalSize => _physicalSize ?? _view.physicalSize;
  Size? _physicalSize;
  set physicalSize(Size value) {
    _physicalSize = value;
    // For backwards compatibility the constraints are set based on the provided size.
    physicalConstraints = ViewConstraints.tight(value);
  }

  /// Resets [physicalSize] (and implicitly also the [physicalConstraints]) to
  /// the default value for this view.
  void resetPhysicalSize() {
    _physicalSize = null;
    resetPhysicalConstraints();
  }

  /// The physical constraints to use for this test.
  ///
  /// Defaults to the value provided by [FlutterView.physicalConstraints]. This
  /// can only be set in a test environment to emulate different view
  /// configurations. A standard [FlutterView] is not mutable from the framework.
  ///
  /// See also:
  ///
  ///   * [FlutterView.physicalConstraints] for the standard implementation
  ///   * [physicalConstraints] to reset this value specifically
  ///   * [reset] to reset all test values for this view
  @override
  ViewConstraints get physicalConstraints => _physicalConstraints ?? _view.physicalConstraints;
  ViewConstraints? _physicalConstraints;
  set physicalConstraints(ViewConstraints value) {
    _physicalConstraints = value;
    platformDispatcher.onMetricsChanged?.call();
  }

  /// Resets [physicalConstraints] to the default value for this view.
  void resetPhysicalConstraints() {
    _physicalConstraints = null;
    platformDispatcher.onMetricsChanged?.call();
  }

  /// The system gesture insets to use for this test.
  ///
  /// Defaults to the value provided by [FlutterView.systemGestureInsets].
  /// This can only be set in a test environment to emulate different view
  /// configurations. A standard [FlutterView] is not mutable from the framework.
  ///
  /// See also:
  ///
  ///   * [FakeViewPadding] which is used to set this value for testing
  ///   * [FlutterView.systemGestureInsets] for the standard implementation
  ///   * [resetSystemGestureInsets] to reset this value specifically
  ///   * [reset] to reset all test values for this view
  @override
  FakeViewPadding get systemGestureInsets => _systemGestureInsets ?? FakeViewPadding._wrap(_view.systemGestureInsets);
  FakeViewPadding? _systemGestureInsets;
  set systemGestureInsets(FakeViewPadding value) {
    _systemGestureInsets = value;
    platformDispatcher.onMetricsChanged?.call();
  }

  /// Resets [systemGestureInsets] to the default value for this view.
  void resetSystemGestureInsets() {
    _systemGestureInsets = null;
    platformDispatcher.onMetricsChanged?.call();
  }

  /// The view insets to use for this test.
  ///
  /// Defaults to the value provided by [FlutterView.viewInsets]. This
  /// can only be set in a test environment to emulate different view
  /// configurations. A standard [FlutterView] is not mutable from the framework.
  ///
  /// See also:
  ///
  ///   * [FakeViewPadding] which is used to set this value for testing
  ///   * [FlutterView.viewInsets] for the standard implementation
  ///   * [resetViewInsets] to reset this value specifically
  ///   * [reset] to reset all test values for this view
  @override
  FakeViewPadding get viewInsets => _viewInsets ?? FakeViewPadding._wrap(_view.viewInsets);
  FakeViewPadding? _viewInsets;
  set viewInsets(FakeViewPadding value) {
    _viewInsets = value;
    platformDispatcher.onMetricsChanged?.call();
  }

  /// Resets [viewInsets] to the default value for this view.
  void resetViewInsets() {
    _viewInsets = null;
    platformDispatcher.onMetricsChanged?.call();
  }

  /// The view padding to use for this test.
  ///
  /// Defaults to the value provided by [FlutterView.viewPadding]. This
  /// can only be set in a test environment to emulate different view
  /// configurations. A standard [FlutterView] is not mutable from the framework.
  ///
  /// See also:
  ///
  ///   * [FakeViewPadding] which is used to set this value for testing
  ///   * [FlutterView.viewPadding] for the standard implementation
  ///   * [resetViewPadding] to reset this value specifically
  ///   * [reset] to reset all test values for this view
  @override
  FakeViewPadding get viewPadding => _viewPadding ?? FakeViewPadding._wrap(_view.viewPadding);
  FakeViewPadding? _viewPadding;
  set viewPadding(FakeViewPadding value) {
    _viewPadding = value;
    platformDispatcher.onMetricsChanged?.call();
  }

  /// Resets [viewPadding] to the default value for this view.
  void resetViewPadding() {
    _viewPadding = null;
    platformDispatcher.onMetricsChanged?.call();
  }

  /// The gesture settings to use for this test.
  ///
  /// Defaults to the value provided by [FlutterView.gestureSettings]. This
  /// can only be set in a test environment to emulate different view
  /// configurations. A standard [FlutterView] is not mutable from the framework.
  ///
  /// See also:
  ///
  ///   * [FlutterView.gestureSettings] for the standard implementation
  ///   * [resetGestureSettings] to reset this value specifically
  ///   * [reset] to reset all test values for this view
  @override
  GestureSettings get gestureSettings => _gestureSettings ?? _view.gestureSettings;
  GestureSettings? _gestureSettings;
  set gestureSettings(GestureSettings value) {
    _gestureSettings = value;
    platformDispatcher.onMetricsChanged?.call();
  }

  /// Resets [gestureSettings] to the default value for this view.
  void resetGestureSettings() {
    _gestureSettings = null;
    platformDispatcher.onMetricsChanged?.call();
  }

  @override
  void render(Scene scene, {Size? size}) {
    _view.render(scene, size: size);
  }

  @override
  void updateSemantics(SemanticsUpdate update) {
    _view.updateSemantics(update);
  }

  /// Resets all test values to the defaults for this view.
  ///
  /// See also:
  ///
  ///   * [resetDevicePixelRatio] to reset [devicePixelRatio] specifically
  ///   * [resetDisplayFeatures]  to reset [displayFeatures] specifically
  ///   * [resetPadding] to reset [padding] specifically
  ///   * [resetPhysicalSize] to reset [physicalSize] specifically
  ///   * [resetSystemGestureInsets] to reset [systemGestureInsets] specifically
  ///   * [resetViewInsets] to reset [viewInsets] specifically
  ///   * [resetViewPadding] to reset [viewPadding] specifically
  ///   * [resetGestureSettings] to reset [gestureSettings] specifically
  void reset() {
    resetDevicePixelRatio();
    resetDisplayFeatures();
    resetPadding();
    resetPhysicalSize();
    // resetPhysicalConstraints is implicitly called by resetPhysicalSize.
    resetSystemGestureInsets();
    resetViewInsets();
    resetViewPadding();
    resetGestureSettings();
  }

  /// This gives us some grace time when the dart:ui side adds something to
  /// [FlutterView], and makes things easier when we do rolls to give
  /// us time to catch up.
  @override
  dynamic noSuchMethod(Invocation invocation) {
    return null;
  }
}

/// A version of [Display] that can be modified to allow for testing various
/// use cases.
///
/// Updates to the [TestDisplay] will be surfaced through
/// [PlatformDispatcher.onMetricsChanged].
class TestDisplay implements Display {
  /// Creates a new [TestDisplay] backed by the given [Display].
  TestDisplay(TestPlatformDispatcher platformDispatcher, Display display)
  : _platformDispatcher = platformDispatcher, _display = display;

  final Display _display;
  final TestPlatformDispatcher _platformDispatcher;

  @override
  int get id => _display.id;

  /// The device pixel ratio to use for this test.
  ///
  /// Defaults to the value provided by [Display.devicePixelRatio]. This
  /// can only be set in a test environment to emulate different display
  /// configurations. A standard [Display] is not mutable from the framework.
  ///
  /// See also:
  ///
  ///   * [Display.devicePixelRatio] for the standard implementation
  ///   * [TestFlutterView.devicePixelRatio] which will stay in sync with this value
  ///   * [resetDevicePixelRatio] to reset this value specifically
  ///   * [reset] to reset all test values for this display
  @override
  double get devicePixelRatio => _devicePixelRatio ?? _display.devicePixelRatio;
  double? _devicePixelRatio;
  set devicePixelRatio(double value) {
    _devicePixelRatio = value;
    _platformDispatcher.onMetricsChanged?.call();
  }

  /// Resets [devicePixelRatio] to the default value for this display.
  ///
  /// This will also reset the [devicePixelRatio] for any [TestFlutterView]s
  /// that are related to this display.
  void resetDevicePixelRatio() {
    _devicePixelRatio = null;
    _platformDispatcher.onMetricsChanged?.call();
  }

  /// The refresh rate to use for this test.
  ///
  /// Defaults to the value provided by [Display.refreshRate]. This
  /// can only be set in a test environment to emulate different display
  /// configurations. A standard [Display] is not mutable from the framework.
  ///
  /// See also:
  ///
  ///   * [Display.refreshRate] for the standard implementation
  ///   * [resetRefreshRate] to reset this value specifically
  ///   * [reset] to reset all test values for this display
  @override
  double get refreshRate => _refreshRate ?? _display.refreshRate;
  double? _refreshRate;
  set refreshRate(double value) {
    _refreshRate = value;
    _platformDispatcher.onMetricsChanged?.call();
  }

  /// Resets [refreshRate] to the default value for this display.
  void resetRefreshRate() {
    _refreshRate = null;
    _platformDispatcher.onMetricsChanged?.call();
  }

  /// The size of the [Display] to use for this test.
  ///
  /// Defaults to the value provided by [Display.refreshRate]. This
  /// can only be set in a test environment to emulate different display
  /// configurations. A standard [Display] is not mutable from the framework.
  ///
  /// See also:
  ///
  ///   * [Display.refreshRate] for the standard implementation
  ///   * [resetRefreshRate] to reset this value specifically
  ///   * [reset] to reset all test values for this display
  @override
  Size get size => _size ?? _display.size;
  Size? _size;
  set size(Size value) {
    _size = value;
    _platformDispatcher.onMetricsChanged?.call();
  }

  /// Resets [size] to the default value for this display.
  void resetSize() {
    _size = null;
    _platformDispatcher.onMetricsChanged?.call();
  }

  /// Resets all values on this [TestDisplay].
  ///
  /// See also:
  ///   * [resetDevicePixelRatio] to reset [devicePixelRatio] specifically
  ///   * [resetRefreshRate] to reset [refreshRate] specifically
  ///   * [resetSize] to reset [size] specifically
  void reset() {
    resetDevicePixelRatio();
    resetRefreshRate();
    resetSize();
  }

  /// This gives us some grace time when the dart:ui side adds something to
  /// [Display], and makes things easier when we do rolls to give
  /// us time to catch up.
  @override
  dynamic noSuchMethod(Invocation invocation) {
    return null;
  }
}

// TODO(pdblasi-google): Remove this once the Display API is stable and supported on all platforms
class _UnsupportedDisplay implements TestDisplay {
  _UnsupportedDisplay(this._platformDispatcher, this._view, this.error);

  final FlutterView _view;
  final Object? error;

  @override
  final TestPlatformDispatcher _platformDispatcher;

  @override
  double get devicePixelRatio => _devicePixelRatio ?? _view.devicePixelRatio;
  @override
  double? _devicePixelRatio;
  @override
  set devicePixelRatio(double value) {
    _devicePixelRatio = value;
    _platformDispatcher.onMetricsChanged?.call();
  }

  @override
  void resetDevicePixelRatio() {
    _devicePixelRatio = null;
    _platformDispatcher.onMetricsChanged?.call();
  }

  @override
  dynamic noSuchMethod(Invocation invocation) {
    throw UnsupportedError(
      'The Display API is unsupported in this context. '
      'As of the last metrics change on PlatformDispatcher, this was the error '
      'given when trying to prepare the display for testing: $error',
    );
  }
}

/// Deprecated. Will be removed in a future version of Flutter.
///
/// This class has been deprecated to prepare for Flutter's upcoming support
/// for multiple views and multiple windows.
///
/// [SingletonFlutterWindow] that wraps another [SingletonFlutterWindow] and
/// allows faking of some properties for testing purposes.
///
/// Tests for certain widgets, e.g., [MaterialApp], might require faking certain
/// properties of a [SingletonFlutterWindow]. [TestWindow] facilitates the
/// faking of these properties by overriding the properties of a real
/// [SingletonFlutterWindow] with desired fake values. The binding used within
/// tests, [TestWidgetsFlutterBinding], contains a [TestWindow] that is used by
/// all tests.
///
/// ## Sample Code
///
/// A test can utilize a [TestWindow] in the following way:
///
/// ```dart
/// testWidgets('your test name here', (WidgetTester tester) async {
///   // Retrieve the TestWidgetsFlutterBinding.
///   final TestWidgetsFlutterBinding testBinding = tester.binding;
///
///   // Fake the desired properties of the TestWindow. All code running
///   // within this test will perceive the following fake text scale
///   // factor as the real text scale factor of the window.
///   testBinding.platformDispatcher.textScaleFactorTestValue = 2.5;
///
///   // Test code that depends on text scale factor here.
/// });
/// ```
///
/// The [TestWidgetsFlutterBinding] is recreated for each test and
/// therefore any fake values defined in one test will not persist
/// to the next.
///
/// If a test needs to override a real [SingletonFlutterWindow] property and
/// then later return to using the real [SingletonFlutterWindow] property,
/// [TestWindow] provides methods to clear each individual test value, e.g.,
/// [clearDevicePixelRatioTestValue].
///
/// To clear all fake test values in a [TestWindow], consider using
/// [clearAllTestValues].
///
/// See also:
///
///   * [TestPlatformDispatcher], which wraps a [PlatformDispatcher] for
///     testing purposes and is used by the [platformDispatcher] property of
///     this class.
@Deprecated(
  'Use TestPlatformDispatcher (via WidgetTester.platformDispatcher) or TestFlutterView (via WidgetTester.view) instead. '
  'Deprecated to prepare for the upcoming multi-window support. '
  'This feature was deprecated after v3.9.0-0.1.pre.'
)
class TestWindow implements SingletonFlutterWindow {
  /// Constructs a [TestWindow] that defers all behavior to the given
  /// [SingletonFlutterWindow] unless explicitly overridden for test purposes.
  @Deprecated(
    'Use TestPlatformDispatcher (via WidgetTester.platformDispatcher) or TestFlutterView (via WidgetTester.view) instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  TestWindow({
    required SingletonFlutterWindow window,
  }) : platformDispatcher = TestPlatformDispatcher(platformDispatcher: window.platformDispatcher);

  /// Constructs a [TestWindow] that defers all behavior to the given
  /// [TestPlatformDispatcher] and its [TestPlatformDispatcher.implicitView].
  ///
  /// This class will not work when multiple views are present. If multiple view
  /// support is needed use [WidgetTester.platformDispatcher] and
  /// [WidgetTester.viewOf].
  ///
  /// See also:
  ///
  ///   * [TestPlatformDispatcher] which allows faking of platform-wide values for
  ///     testing purposes.
  ///   * [TestFlutterView] which allows faking of view-specific values for
  ///     testing purposes.
  @Deprecated(
    'Use TestPlatformDispatcher (via WidgetTester.platformDispatcher) or TestFlutterView (via WidgetTester.view) instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  TestWindow.fromPlatformDispatcher({
    @Deprecated(
      'Use WidgetTester.platformDispatcher instead. '
      'Deprecated to prepare for the upcoming multi-window support. '
      'This feature was deprecated after v3.9.0-0.1.pre.'
    )
    required this.platformDispatcher,
  });

  @Deprecated(
    'Use WidgetTester.platformDispatcher instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  final TestPlatformDispatcher platformDispatcher;

  TestFlutterView get _view => platformDispatcher.implicitView!;

  @Deprecated(
    'Use WidgetTester.view.devicePixelRatio instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  double get devicePixelRatio => _view.devicePixelRatio;
  /// Hides the real device pixel ratio and reports the given [devicePixelRatio]
  /// instead.
  @Deprecated(
    'Use WidgetTester.view.devicePixelRatio instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  set devicePixelRatioTestValue(double devicePixelRatio) { // ignore: avoid_setters_without_getters
    _view.devicePixelRatio = devicePixelRatio;
  }

  /// Deletes any existing test device pixel ratio and returns to using the real
  /// device pixel ratio.
  @Deprecated(
    'Use WidgetTester.view.resetDevicePixelRatio() instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  void clearDevicePixelRatioTestValue() {
    _view.resetDevicePixelRatio();
  }

  @Deprecated(
    'Use WidgetTester.view.physicalSize instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  Size get physicalSize => _view.physicalSize;
  /// Hides the real physical size and reports the given [physicalSizeTestValue]
  /// instead.
  @Deprecated(
    'Use WidgetTester.view.physicalSize instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  set physicalSizeTestValue (Size physicalSizeTestValue) { // ignore: avoid_setters_without_getters
    _view.physicalSize = physicalSizeTestValue;
  }

  /// Deletes any existing test physical size and returns to using the real
  /// physical size.
  @Deprecated(
    'Use WidgetTester.view.resetPhysicalSize() instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  void clearPhysicalSizeTestValue() {
    _view.resetPhysicalSize();
  }

  @Deprecated(
    'Use WidgetTester.view.viewInsets instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  ViewPadding get viewInsets => _view.viewInsets;
  /// Hides the real view insets and reports the given [viewInsetsTestValue]
  /// instead.
  ///
  /// Use [FakeViewPadding] to set this value for testing.
  @Deprecated(
    'Use WidgetTester.view.viewInsets instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  set viewInsetsTestValue(ViewPadding value) { // ignore: avoid_setters_without_getters
    _view.viewInsets = value is FakeViewPadding ? value : FakeViewPadding._wrap(value);
  }

  /// Deletes any existing test view insets and returns to using the real view
  /// insets.
  @Deprecated(
    'Use WidgetTester.view.resetViewInsets() instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  void clearViewInsetsTestValue() {
    _view.resetViewInsets();
  }

  @Deprecated(
    'Use WidgetTester.view.viewPadding instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  ViewPadding get viewPadding => _view.viewPadding;
  /// Hides the real view padding and reports the given [paddingTestValue]
  /// instead.
  ///
  /// Use [FakeViewPadding] to set this value for testing.
  @Deprecated(
    'Use WidgetTester.view.viewPadding instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  set viewPaddingTestValue(ViewPadding value) { // ignore: avoid_setters_without_getters
    _view.viewPadding = value is FakeViewPadding ? value : FakeViewPadding._wrap(value);
  }

  /// Deletes any existing test view padding and returns to using the real
  /// viewPadding.
  @Deprecated(
    'Use WidgetTester.view.resetViewPadding() instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  void clearViewPaddingTestValue() {
    _view.resetViewPadding();
  }

  @Deprecated(
    'Use WidgetTester.view.padding instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  ViewPadding get padding => _view.padding;
  /// Hides the real padding and reports the given [paddingTestValue] instead.
  ///
  /// Use [FakeViewPadding] to set this value for testing.
  @Deprecated(
    'Use WidgetTester.view.padding instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  set paddingTestValue(ViewPadding value) { // ignore: avoid_setters_without_getters
    _view.padding = value is FakeViewPadding ? value : FakeViewPadding._wrap(value);
  }

  /// Deletes any existing test padding and returns to using the real padding.
  @Deprecated(
    'Use WidgetTester.view.resetPadding() instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  void clearPaddingTestValue() {
    _view.resetPadding();
  }

  @Deprecated(
    'Use WidgetTester.view.gestureSettings instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  GestureSettings get gestureSettings => _view.gestureSettings;
  /// Hides the real gesture settings and reports the given [gestureSettingsTestValue] instead.
  @Deprecated(
    'Use WidgetTester.view.gestureSettings instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  set gestureSettingsTestValue(GestureSettings gestureSettingsTestValue) { // ignore: avoid_setters_without_getters
    _view.gestureSettings = gestureSettingsTestValue;
  }

  /// Deletes any existing test gesture settings and returns to using the real gesture settings.
  @Deprecated(
    'Use WidgetTester.view.resetGestureSettings() instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  void clearGestureSettingsTestValue() {
    _view.resetGestureSettings();
  }

  @Deprecated(
    'Use WidgetTester.view.displayFeatures instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  List<DisplayFeature> get displayFeatures => _view.displayFeatures;
  /// Hides the real displayFeatures and reports the given [displayFeaturesTestValue] instead.
  @Deprecated(
    'Use WidgetTester.view.displayFeatures instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  set displayFeaturesTestValue(List<DisplayFeature> displayFeaturesTestValue) { // ignore: avoid_setters_without_getters
    _view.displayFeatures = displayFeaturesTestValue;
  }

  /// Deletes any existing test padding and returns to using the real padding.
  @Deprecated(
    'Use WidgetTester.view.resetDisplayFeatures() instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  void clearDisplayFeaturesTestValue() {
    _view.resetDisplayFeatures();
  }

  @Deprecated(
    'Use WidgetTester.view.systemGestureInsets instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  ViewPadding get systemGestureInsets => _view.systemGestureInsets;
  /// Hides the real system gesture insets and reports the given
  /// [systemGestureInsetsTestValue] instead.
  ///
  /// Use [FakeViewPadding] to set this value for testing.
  @Deprecated(
    'Use WidgetTester.view.systemGestureInsets instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  set systemGestureInsetsTestValue(ViewPadding value) { // ignore: avoid_setters_without_getters
    _view.systemGestureInsets = value is FakeViewPadding ? value : FakeViewPadding._wrap(value);
  }

  /// Deletes any existing test system gesture insets and returns to using the real system gesture insets.
  @Deprecated(
    'Use WidgetTester.view.resetSystemGestureInsets() instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  void clearSystemGestureInsetsTestValue() {
    _view.resetSystemGestureInsets();
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.onMetricsChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  VoidCallback? get onMetricsChanged => platformDispatcher.onMetricsChanged;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onMetricsChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  set onMetricsChanged(VoidCallback? callback) {
    platformDispatcher.onMetricsChanged = callback;
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.locale instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  Locale get locale => platformDispatcher.locale;

  @Deprecated(
    'Use WidgetTester.platformDispatcher.locales instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  List<Locale> get locales => platformDispatcher.locales;

  @Deprecated(
    'Use WidgetTester.platformDispatcher.onLocaleChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  VoidCallback? get onLocaleChanged => platformDispatcher.onLocaleChanged;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onLocaleChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  set onLocaleChanged(VoidCallback? callback) {
    platformDispatcher.onLocaleChanged = callback;
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.initialLifecycleState instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  String get initialLifecycleState => platformDispatcher.initialLifecycleState;

  @Deprecated(
    'Use WidgetTester.platformDispatcher.textScaleFactor instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  double get textScaleFactor => platformDispatcher.textScaleFactor;

  @Deprecated(
    'Use WidgetTester.platformDispatcher.platformBrightness instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  Brightness get platformBrightness => platformDispatcher.platformBrightness;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onPlatformBrightnessChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  VoidCallback? get onPlatformBrightnessChanged => platformDispatcher.onPlatformBrightnessChanged;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onPlatformBrightnessChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  set onPlatformBrightnessChanged(VoidCallback? callback) {
    platformDispatcher.onPlatformBrightnessChanged = callback;
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.alwaysUse24HourFormat instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  bool get alwaysUse24HourFormat => platformDispatcher.alwaysUse24HourFormat;

  @Deprecated(
    'Use WidgetTester.platformDispatcher.onTextScaleFactorChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  VoidCallback? get onTextScaleFactorChanged => platformDispatcher.onTextScaleFactorChanged;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onTextScaleFactorChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  set onTextScaleFactorChanged(VoidCallback? callback) {
    platformDispatcher.onTextScaleFactorChanged = callback;
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.nativeSpellCheckServiceDefined instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  bool get nativeSpellCheckServiceDefined => platformDispatcher.nativeSpellCheckServiceDefined;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.nativeSpellCheckServiceDefinedTestValue instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  set nativeSpellCheckServiceDefinedTestValue(bool nativeSpellCheckServiceDefinedTestValue) { // ignore: avoid_setters_without_getters
    platformDispatcher.nativeSpellCheckServiceDefinedTestValue = nativeSpellCheckServiceDefinedTestValue;
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.brieflyShowPassword instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  bool get brieflyShowPassword => platformDispatcher.brieflyShowPassword;

  @Deprecated(
    'Use WidgetTester.platformDispatcher.onBeginFrame instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  FrameCallback? get onBeginFrame => platformDispatcher.onBeginFrame;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onBeginFrame instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  set onBeginFrame(FrameCallback? callback) {
    platformDispatcher.onBeginFrame = callback;
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.onDrawFrame instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  VoidCallback? get onDrawFrame => platformDispatcher.onDrawFrame;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onDrawFrame instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  set onDrawFrame(VoidCallback? callback) {
    platformDispatcher.onDrawFrame = callback;
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.onReportTimings instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  TimingsCallback? get onReportTimings => platformDispatcher.onReportTimings;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onReportTimings instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  set onReportTimings(TimingsCallback? callback) {
    platformDispatcher.onReportTimings = callback;
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.onPointerDataPacket instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  PointerDataPacketCallback? get onPointerDataPacket => platformDispatcher.onPointerDataPacket;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onPointerDataPacket instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  set onPointerDataPacket(PointerDataPacketCallback? callback) {
    platformDispatcher.onPointerDataPacket = callback;
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.defaultRouteName instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  String get defaultRouteName => platformDispatcher.defaultRouteName;

  @Deprecated(
    'Use WidgetTester.platformDispatcher.scheduleFrame() instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  void scheduleFrame() {
    platformDispatcher.scheduleFrame();
  }

  @Deprecated(
    'Use WidgetTester.view.render(scene) instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  void render(Scene scene, {Size? size}) {
    _view.render(scene, size: size);
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.semanticsEnabled instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  bool get semanticsEnabled => platformDispatcher.semanticsEnabled;

  @Deprecated(
    'Use WidgetTester.platformDispatcher.onSemanticsEnabledChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  VoidCallback? get onSemanticsEnabledChanged => platformDispatcher.onSemanticsEnabledChanged;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onSemanticsEnabledChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  set onSemanticsEnabledChanged(VoidCallback? callback) {
    platformDispatcher.onSemanticsEnabledChanged = callback;
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.accessibilityFeatures instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  AccessibilityFeatures get accessibilityFeatures => platformDispatcher.accessibilityFeatures;

  @Deprecated(
    'Use WidgetTester.platformDispatcher.onAccessibilityFeaturesChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  VoidCallback? get onAccessibilityFeaturesChanged => platformDispatcher.onAccessibilityFeaturesChanged;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onAccessibilityFeaturesChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  set onAccessibilityFeaturesChanged(VoidCallback? callback) {
    platformDispatcher.onAccessibilityFeaturesChanged = callback;
  }

  @Deprecated(
    'Use WidgetTester.view.updateSemantics(update) instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  void updateSemantics(SemanticsUpdate update) {
    _view.updateSemantics(update);
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.setIsolateDebugName(name) instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  void setIsolateDebugName(String name) {
    platformDispatcher.setIsolateDebugName(name);
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.sendPlatformMessage(name, data, callback) instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  void sendPlatformMessage(
    String name,
    ByteData? data,
    PlatformMessageResponseCallback? callback,
  ) {
    platformDispatcher.sendPlatformMessage(name, data, callback);
  }

  /// Delete any test value properties that have been set on this [TestWindow]
  /// as well as its [platformDispatcher].
  ///
  /// After calling this, the real [SingletonFlutterWindow] and
  /// [PlatformDispatcher] values are reported again.
  ///
  /// If desired, clearing of properties can be done on an individual basis,
  /// e.g., [clearDevicePixelRatioTestValue].
  @Deprecated(
    'Use WidgetTester.platformDispatcher.clearAllTestValues() and WidgetTester.view.reset() instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  void clearAllTestValues() {
    clearDevicePixelRatioTestValue();
    clearPaddingTestValue();
    clearGestureSettingsTestValue();
    clearDisplayFeaturesTestValue();
    clearPhysicalSizeTestValue();
    clearViewInsetsTestValue();
    platformDispatcher.clearAllTestValues();
  }

  @override
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onFrameDataChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  VoidCallback? get onFrameDataChanged => platformDispatcher.onFrameDataChanged;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onFrameDataChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  set onFrameDataChanged(VoidCallback? value) {
    platformDispatcher.onFrameDataChanged = value;
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.onKeyData instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  KeyDataCallback? get onKeyData => platformDispatcher.onKeyData;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onKeyData instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  set onKeyData(KeyDataCallback? value) {
    platformDispatcher.onKeyData = value;
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.onSystemFontFamilyChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  VoidCallback? get onSystemFontFamilyChanged => platformDispatcher.onSystemFontFamilyChanged;
  @Deprecated(
    'Use WidgetTester.platformDispatcher.onSystemFontFamilyChanged instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  set onSystemFontFamilyChanged(VoidCallback? value) {
    platformDispatcher.onSystemFontFamilyChanged = value;
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.computePlatformResolvedLocale(supportedLocales) instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  Locale? computePlatformResolvedLocale(List<Locale> supportedLocales) {
    return platformDispatcher.computePlatformResolvedLocale(supportedLocales);
  }

  @Deprecated(
    'Use WidgetTester.platformDispatcher.frameData instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  FrameData get frameData => platformDispatcher.frameData;

  @Deprecated(
    'Use WidgetTester.platformDispatcher.systemFontFamily instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  String? get systemFontFamily => platformDispatcher.systemFontFamily;

  @Deprecated(
    'Use WidgetTester.view.viewId instead. '
    'Deprecated to prepare for the upcoming multi-window support. '
    'This feature was deprecated after v3.9.0-0.1.pre.'
  )
  @override
  int get viewId => _view.viewId;

  /// This gives us some grace time when the dart:ui side adds something to
  /// [SingletonFlutterWindow], and makes things easier when we do rolls to give
  /// us time to catch up.
  @override
  dynamic noSuchMethod(Invocation invocation) {
    return null;
  }
}
