// 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 'package:meta/meta.dart';
import 'package:ui/ui.dart' as ui;

import '../dom.dart';
import '../platform_dispatcher.dart';
import '../services/message_codec.dart';
import '../services/message_codecs.dart';
import 'url_strategy.dart';

/// Infers the history mode from the existing browser history state, then
/// creates the appropriate instance of [BrowserHistory] for it.
///
/// If it can't infer, it creates a [MultiEntriesBrowserHistory] by default.
BrowserHistory createHistoryForExistingState(UrlStrategy? urlStrategy) {
  if (urlStrategy != null) {
    final Object? state = urlStrategy.getState();
    if (SingleEntryBrowserHistory._isOriginEntry(state) || SingleEntryBrowserHistory._isFlutterEntry(state)) {
      return SingleEntryBrowserHistory(urlStrategy: urlStrategy);
    }
  }
  return MultiEntriesBrowserHistory(urlStrategy: urlStrategy);
}

/// An abstract class that provides the API for [EngineWindow] to delegate its
/// navigating events.
///
/// Subclasses will have access to [BrowserHistory.locationStrategy] to
/// interact with the html browser history and should come up with their own
/// ways to manage the states in the browser history.
///
/// There should only be one global instance among all subclasses.
///
/// See also:
///
///  * [SingleEntryBrowserHistory]: which creates a single fake browser history
///    entry and delegates all browser navigating events to the flutter
///    framework.
///  * [MultiEntriesBrowserHistory]: which creates a set of states that records
///    the navigating events happened in the framework.
abstract class BrowserHistory {
  late ui.VoidCallback _unsubscribe;

  /// The strategy to interact with html browser history.
  UrlStrategy? get urlStrategy;

  bool _isTornDown = false;
  bool _isDisposed = false;

  void _setupStrategy(UrlStrategy strategy) {
    _unsubscribe = strategy.addPopStateListener(onPopState as DomEventListener);
  }

  /// Release any resources held by this [BrowserHistory] instance.
  ///
  /// This method has no effect on the browser history entries. Use [tearDown]
  /// instead to revert this instance's modifications to browser history
  /// entries.
  @mustCallSuper
  void dispose() {
    if (_isDisposed || urlStrategy == null) {
      return;
    }
    _isDisposed = true;
    _unsubscribe();
  }

  /// Exit this application and return to the previous page.
  Future<void> exit() async {
    if (urlStrategy != null) {
      await tearDown();
      // Now the history should be in the original state, back one more time to
      // exit the application.
      await urlStrategy!.go(-1);
    }
  }

  /// This method does the same thing as the browser back button.
  Future<void> back() async {
    return urlStrategy?.go(-1);
  }

  /// The path of the current location of the user's browser.
  String get currentPath => urlStrategy?.getPath() ?? '/';

  /// The state of the current location of the user's browser.
  Object? get currentState => urlStrategy?.getState();

  /// Update the url with the given `routeName` and `state`.
  ///
  /// If `replace` is false, the caller wants to push a new `routeName` and
  /// `state` on top of the existing ones; otherwise, the caller wants to replace
  /// the current `routeName` and `state` with the new ones.
  void setRouteName(String? routeName, {Object? state, bool replace = false});

  /// A callback method to handle browser backward or forward buttons.
  ///
  /// Subclasses should send appropriate system messages to update the flutter
  /// applications accordingly.
  void onPopState(covariant DomPopStateEvent event);

  /// Restore any modifications to the html browser history during the lifetime
  /// of this class.
  Future<void> tearDown();
}

/// A browser history class that creates a set of browser history entries to
/// support browser backward and forward button natively.
///
/// This class pushes a browser history entry every time the framework reports
/// a route change and sends a `pushRouteInformation` method call to the
/// framework when the browser jumps to a specific browser history entry.
///
/// The web engine uses this class to manage its browser history when the
/// framework uses a Router for routing.
///
/// See also:
///
/// * [SingleEntryBrowserHistory], which is used when the framework does not use
///   a Router for routing.
class MultiEntriesBrowserHistory extends BrowserHistory {
  MultiEntriesBrowserHistory({required this.urlStrategy}) {
    final UrlStrategy? strategy = urlStrategy;
    if (strategy == null) {
      return;
    }

    _setupStrategy(strategy);
    if (!_hasSerialCount(currentState)) {
      strategy.replaceState(
          _tagWithSerialCount(currentState, 0), 'flutter', currentPath);
    }
    // If we restore from a page refresh, the _currentSerialCount may not be 0.
    _lastSeenSerialCount = _currentSerialCount;
  }

  @override
  final UrlStrategy? urlStrategy;

  late int _lastSeenSerialCount;
  int get _currentSerialCount {
    if (_hasSerialCount(currentState)) {
      final Map<dynamic, dynamic> stateMap =
          currentState! as Map<dynamic, dynamic>;
      return (stateMap['serialCount'] as double).toInt();
    }
    return 0;
  }

  Object _tagWithSerialCount(Object? originialState, int count) {
    return <dynamic, dynamic>{
      'serialCount': count.toDouble(),
      'state': originialState,
    };
  }

  bool _hasSerialCount(Object? state) {
    return state is Map && state['serialCount'] != null;
  }

  @override
  void setRouteName(String? routeName, {Object? state, bool replace = false}) {
    if (urlStrategy != null) {
      assert(routeName != null);
      if (replace) {
        urlStrategy!.replaceState(
          _tagWithSerialCount(state, _lastSeenSerialCount),
          'flutter',
          routeName!,
        );
      } else {
        _lastSeenSerialCount += 1;
        urlStrategy!.pushState(
          _tagWithSerialCount(state, _lastSeenSerialCount),
          'flutter',
          routeName!,
        );
      }
    }
  }

  @override
  void onPopState(covariant DomPopStateEvent event) {
    assert(urlStrategy != null);
    // May be a result of direct url access while the flutter application is
    // already running.
    if (!_hasSerialCount(event.state)) {
      // In this case we assume this will be the next history entry from the
      // last seen entry.
      urlStrategy!.replaceState(
          _tagWithSerialCount(event.state, _lastSeenSerialCount + 1),
          'flutter',
          currentPath);
    }
    _lastSeenSerialCount = _currentSerialCount;
    EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
      'flutter/navigation',
      const JSONMethodCodec().encodeMethodCall(
          MethodCall('pushRouteInformation', <dynamic, dynamic>{
        'location': currentPath,
        'state': event.state?['state'],
      })),
      (_) {},
    );
  }

  @override
  Future<void> tearDown() async {
    dispose();

    if (_isTornDown || urlStrategy == null) {
      return;
    }
    _isTornDown = true;

    // Restores the html browser history.
    assert(_hasSerialCount(currentState));
    final int backCount = _currentSerialCount;
    if (backCount > 0) {
      await urlStrategy!.go(-backCount.toDouble());
    }
    // Unwrap state.
    assert(_hasSerialCount(currentState) && _currentSerialCount == 0);
    final Map<dynamic, dynamic> stateMap =
        currentState! as Map<dynamic, dynamic>;
    urlStrategy!.replaceState(
      stateMap['state'],
      'flutter',
      currentPath,
    );
  }
}

/// The browser history class is responsible for integrating Flutter Web apps
/// with the browser history so that the back button works as expected.
///
/// It does that by always keeping a single entry (conventionally called the
/// "flutter" entry) at the top of the browser history. That way, the browser's
/// back button always triggers a `popstate` event and never closes the app (we
/// close the app programmatically by calling [SystemNavigator.pop] when there
/// are no more app routes to be popped).
///
/// The web engine uses this class when the framework does not use Router for
/// routing, and it does not support browser forward button.
///
/// See also:
///
///  * [MultiEntriesBrowserHistory], which is used when the framework uses a
///    Router for routing.
class SingleEntryBrowserHistory extends BrowserHistory {
  SingleEntryBrowserHistory({required this.urlStrategy}) {
    final UrlStrategy? strategy = urlStrategy;
    if (strategy == null) {
      return;
    }

    _setupStrategy(strategy);

    final String path = currentPath;
    if (!_isFlutterEntry(domWindow.history.state)) {
      // An entry may not have come from Flutter, for example, when the user
      // refreshes the page. They land directly on the "flutter" entry, so
      // there's no need to set up the "origin" and "flutter" entries, we can
      // safely assume they are already set up.
      _setupOriginEntry(strategy);
      _setupFlutterEntry(strategy, path: path);
    }
  }

  @override
  final UrlStrategy? urlStrategy;

  static const MethodCall _popRouteMethodCall = MethodCall('popRoute');
  static const String _kFlutterTag = 'flutter';
  static const String _kOriginTag = 'origin';

  Map<String, dynamic> _wrapOriginState(Object? state) {
    return <String, dynamic>{_kOriginTag: true, 'state': state};
  }

  Object? _unwrapOriginState(Object? state) {
    assert(_isOriginEntry(state));
    final Map<dynamic, dynamic> originState = state! as Map<dynamic, dynamic>;
    return originState['state'];
  }

  final Map<String, bool> _flutterState = <String, bool>{_kFlutterTag: true};

  /// The origin entry is the history entry that the Flutter app landed on. It's
  /// created by the browser when the user navigates to the url of the app.
  static bool _isOriginEntry(Object? state) {
    return state is Map && state[_kOriginTag] == true;
  }

  /// The flutter entry is a history entry that we maintain on top of the origin
  /// entry. It allows us to catch popstate events when the user hits the back
  /// button.
  static bool _isFlutterEntry(Object? state) {
    return state is Map && state[_kFlutterTag] == true;
  }

  @override
  void setRouteName(String? routeName, {Object? state, bool replace = false}) {
    if (urlStrategy != null) {
      _setupFlutterEntry(urlStrategy!, replace: true, path: routeName);
    }
  }

  String? _userProvidedRouteName;
  @override
  void onPopState(covariant DomPopStateEvent event) {
    if (_isOriginEntry(event.state)) {
      _setupFlutterEntry(urlStrategy!);

      // 2. Send a 'popRoute' platform message so the app can handle it accordingly.
      EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
        'flutter/navigation',
        const JSONMethodCodec().encodeMethodCall(_popRouteMethodCall),
        (_) {},
      );
    } else if (_isFlutterEntry(event.state)) {
      // We get into this scenario when the user changes the url manually. It
      // causes a new entry to be pushed on top of our "flutter" one. When this
      // happens it first goes to the "else" section below where we capture the
      // path into `_userProvidedRouteName` then trigger a history back which
      // brings us here.
      assert(_userProvidedRouteName != null);

      final String newRouteName = _userProvidedRouteName!;
      _userProvidedRouteName = null;

      // Send a 'pushRoute' platform message so the app handles it accordingly.
      EnginePlatformDispatcher.instance.invokeOnPlatformMessage(
        'flutter/navigation',
        const JSONMethodCodec().encodeMethodCall(
          MethodCall('pushRoute', newRouteName),
        ),
        (_) {},
      );
    } else {
      // The user has pushed a new entry on top of our flutter entry. This could
      // happen when the user modifies the hash part of the url directly, for
      // example.

      // 1. We first capture the user's desired path.
      _userProvidedRouteName = currentPath;

      // 2. Then we remove the new entry.
      // This will take us back to our "flutter" entry and it causes a new
      // popstate event that will be handled in the "else if" section above.
      urlStrategy!.go(-1);
    }
  }

  /// This method should be called when the Origin Entry is active. It just
  /// replaces the state of the entry so that we can recognize it later using
  /// [_isOriginEntry] inside [_popStateListener].
  void _setupOriginEntry(UrlStrategy strategy) {
    assert(strategy != null);
    strategy.replaceState(_wrapOriginState(currentState), 'origin', '');
  }

  /// This method is used manipulate the Flutter Entry which is always the
  /// active entry while the Flutter app is running.
  void _setupFlutterEntry(
    UrlStrategy strategy, {
    bool replace = false,
    String? path,
  }) {
    assert(strategy != null);
    path ??= currentPath;
    if (replace) {
      strategy.replaceState(_flutterState, 'flutter', path);
    } else {
      strategy.pushState(_flutterState, 'flutter', path);
    }
  }

  @override
  Future<void> tearDown() async {
    dispose();

    if (_isTornDown || urlStrategy == null) {
      return;
    }
    _isTornDown = true;

    // We need to remove the flutter entry that we pushed in setup.
    await urlStrategy!.go(-1);
    // Restores original state.
    urlStrategy!
        .replaceState(_unwrapOriginState(currentState), 'flutter', currentPath);
  }
}
