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

@JS()
library window;

import 'dart:async';
import 'dart:typed_data';

import 'package:js/js.dart';
import 'package:meta/meta.dart';
import 'package:ui/ui.dart' as ui;

import '../engine.dart' show DimensionsProvider, registerHotRestartListener, renderer;
import 'dom.dart';
import 'navigation/history.dart';
import 'navigation/js_url_strategy.dart';
import 'navigation/url_strategy.dart';
import 'platform_dispatcher.dart';
import 'services.dart';
import 'test_embedding.dart';
import 'util.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;

/// Whether [_customUrlStrategy] has been set or not.
///
/// It is valid to set [_customUrlStrategy] to null, so we can't use a null
/// check to determine whether it was set or not. We need an extra boolean.
bool _isUrlStrategySet = false;

/// A custom URL strategy set by the app before running.
UrlStrategy? _customUrlStrategy;
set customUrlStrategy(UrlStrategy? strategy) {
  assert(!_isUrlStrategySet, 'Cannot set URL strategy more than once.');
  _isUrlStrategySet = true;
  _customUrlStrategy = strategy;
}

/// The Web implementation of [ui.SingletonFlutterWindow].
class EngineFlutterWindow extends ui.SingletonFlutterWindow {
  EngineFlutterWindow(this.viewId, this.platformDispatcher) {
    final EnginePlatformDispatcher engineDispatcher =
        platformDispatcher as EnginePlatformDispatcher;
    engineDispatcher.viewData[viewId] = this;
    engineDispatcher.windowConfigurations[viewId] = const ViewConfiguration();
    if (_isUrlStrategySet) {
      _browserHistory = createHistoryForExistingState(_customUrlStrategy);
    }
    registerHotRestartListener(() {
      _browserHistory?.dispose();
      renderer.clearFragmentProgramCache();
      _dimensionsProvider.close();
    });
  }

  @override
  final Object viewId;

  @override
  final ui.PlatformDispatcher platformDispatcher;

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

  UrlStrategy? get _urlStrategyForInitialization {
    final UrlStrategy? urlStrategy =
        _isUrlStrategySet ? _customUrlStrategy : _createDefaultUrlStrategy();
    // Prevent any further customization of URL strategy.
    _isUrlStrategySet = true;
    return 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 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 UrlStrategy? strategy = _browserHistory?.urlStrategy;
    await _browserHistory?.tearDown();
    _browserHistory = MultiEntriesBrowserHistory(urlStrategy: strategy);
  }

  @visibleForTesting
  Future<void> debugInitializeHistory(
    UrlStrategy? strategy, {
    required bool useSingle,
  }) async {
    // Prevent any further customization of URL strategy.
    _isUrlStrategySet = true;
    await _browserHistory?.tearDown();
    if (useSingle) {
      _browserHistory = SingleEntryBrowserHistory(urlStrategy: strategy);
    } else {
      _browserHistory = MultiEntriesBrowserHistory(urlStrategy: strategy);
    }
  }

  Future<void> resetHistory() async {
    await _browserHistory?.tearDown();
    _browserHistory = null;
    // Reset the globals too.
    _isUrlStrategySet = false;
    _customUrlStrategy = null;
  }

  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;
    });
  }

  ViewConfiguration get _viewConfiguration {
    final EnginePlatformDispatcher engineDispatcher =
        platformDispatcher as EnginePlatformDispatcher;
    assert(engineDispatcher.windowConfigurations.containsKey(viewId));
    return engineDispatcher.windowConfigurations[viewId] ??
        const ViewConfiguration();
  }

  @override
  ui.Rect get physicalGeometry => _viewConfiguration.geometry;

  @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;

  late DimensionsProvider _dimensionsProvider;
  void configureDimensionsProvider(DimensionsProvider dimensionsProvider) {
    _dimensionsProvider = dimensionsProvider;
  }

  @override
  double get devicePixelRatio => _dimensionsProvider.getDevicePixelRatio();

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

  @override
  ui.Size get physicalSize {
    if (_physicalSize == null) {
      computePhysicalSize();
    }
    assert(_physicalSize != null);
    return _physicalSize!;
  }

  /// Computes the physical size of the screen from [domWindow].
  ///
  /// This function is expensive. It triggers browser layout if there are
  /// pending DOM writes.
  void computePhysicalSize() {
    bool override = false;

    assert(() {
      if (webOnlyDebugPhysicalSizeOverride != null) {
        _physicalSize = webOnlyDebugPhysicalSizeOverride;
        override = true;
      }
      return true;
    }());

    if (!override) {
      _physicalSize = _dimensionsProvider.computePhysicalSize();
    }
  }

  /// Forces the window to recompute its physical size. Useful for tests.
  void debugForceResize() {
    computePhysicalSize();
  }

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

  /// 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() {
    // This method compares the new dimensions with the previous ones.
    // Return false if the previous dimensions are not set.
    if (_physicalSize != null) {
      final ui.Size current = _dimensionsProvider.computePhysicalSize();
      // First confirm both height and width are effected.
      if (_physicalSize!.height != current.height && _physicalSize!.width != current.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 && current.height < current.width) ||
            (_physicalSize!.width > _physicalSize!.height && current.width < current.height)) {
          // Rotation detected
          return true;
        }
      }
    }
    return false;
  }

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

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

  /// Overrides the value of [physicalSize] in tests.
  ui.Size? webOnlyDebugPhysicalSizeOverride;
}

typedef _JsSetUrlStrategy = void Function(JsUrlStrategy?);

/// A JavaScript hook to customize the URL strategy of a Flutter app.
//
// Keep this js name in sync with flutter_web_plugins. Find it at:
// https://github.com/flutter/flutter/blob/custom_location_strategy/packages/flutter_web_plugins/lib/src/navigation/js_url_strategy.dart
//
// TODO(mdebbar): Add integration test https://github.com/flutter/flutter/issues/66852
@JS('_flutter_web_set_location_strategy')
external set jsSetUrlStrategy(_JsSetUrlStrategy? newJsSetUrlStrategy);

UrlStrategy? _createDefaultUrlStrategy() {
  return ui.debugEmulateFlutterTesterEnvironment
      ? TestUrlStrategy.fromEntry(const TestHistoryEntry('default', null, '/'))
      : const HashUrlStrategy();
}

/// The Web implementation of [ui.SingletonFlutterWindow].
class EngineSingletonFlutterWindow extends EngineFlutterWindow {
  EngineSingletonFlutterWindow(
      super.windowId, super.platformDispatcher);

  @override
  double get devicePixelRatio =>
      _debugDevicePixelRatio ??
      EnginePlatformDispatcher.browserDevicePixelRatio;

  /// Overrides the default device pixel ratio.
  ///
  /// This is useful in tests to emulate screens of different dimensions.
  void debugOverrideDevicePixelRatio(double value) {
    _debugDevicePixelRatio = value;
  }

  double? _debugDevicePixelRatio;
}

/// 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.
final EngineSingletonFlutterWindow window =
    EngineSingletonFlutterWindow(kImplicitViewId, EnginePlatformDispatcher.instance);

/// 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;
}
