// 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 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';

import 'basic.dart';
import 'framework.dart';

export 'package:flutter/services.dart' show RestorationBucket;

/// Creates a new scope for restoration IDs used by descendant widgets to claim
/// [RestorationBucket]s.
///
/// {@template flutter.widgets.RestorationScope}
/// A restoration scope inserts a [RestorationBucket] into the widget tree,
/// which descendant widgets can access via [RestorationScope.of]. It is
/// uncommon for descendants to directly store data in this bucket. Instead,
/// descendant widgets should consider storing their own restoration data in a
/// child bucket claimed with [RestorationBucket.claimChild] from the bucket
/// provided by this scope.
/// {@endtemplate}
///
/// The bucket inserted into the widget tree by this scope has been claimed from
/// the surrounding [RestorationScope] using the provided [restorationId]. If
/// the [RestorationScope] is moved to a different part of the widget tree under
/// a different [RestorationScope], the bucket owned by this scope with all its
/// children and the data contained in them is moved to the new scope as well.
///
/// This widget will not make a [RestorationBucket] available to descendants if
/// [restorationId] is null or when there is no surrounding restoration scope to
/// claim a bucket from. In this case, descendant widgets invoking
/// [RestorationScope.of] will receive null as a return value indicating that no
/// bucket is available for storing restoration data. This will turn off state
/// restoration for the widget subtree.
///
/// See also:
///
///  * [RootRestorationScope], which inserts the root bucket provided by
///    the [RestorationManager] into the widget tree and makes it accessible
///    for descendants via [RestorationScope.of].
///  * [UnmanagedRestorationScope], which inserts a provided [RestorationBucket]
///    into the widget tree and makes it accessible for descendants via
///    [RestorationScope.of].
///  * [RestorationMixin], which may be used in [State] objects to manage the
///    restoration data of a [StatefulWidget] instead of manually interacting
///    with [RestorationScope]s and [RestorationBucket]s.
///  * [RestorationManager], which describes the basic concepts of state
///    restoration in Flutter.
class RestorationScope extends StatefulWidget {
  /// Creates a [RestorationScope].
  ///
  /// Providing null as the [restorationId] turns off state restoration for
  /// the [child] and its descendants.
  ///
  /// The [child] must not be null.
  const RestorationScope({
    super.key,
    required this.restorationId,
    required this.child,
  }) : assert(child != null);

  /// Returns the [RestorationBucket] inserted into the widget tree by the
  /// closest ancestor [RestorationScope] of `context`.
  ///
  /// To avoid accidentally overwriting data already stored in the bucket by its
  /// owner, data should not be stored directly in the bucket returned by this
  /// method. Instead, consider claiming a child bucket from the returned bucket
  /// (via [RestorationBucket.claimChild]) and store the restoration data in
  /// that child.
  ///
  /// This method returns null if state restoration is turned off for this
  /// subtree.
  static RestorationBucket? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<UnmanagedRestorationScope>()?.bucket;
  }

  /// The widget below this widget in the tree.
  ///
  /// {@macro flutter.widgets.ProxyWidget.child}
  final Widget child;

  /// The restoration ID used by this widget to obtain a child bucket from the
  /// surrounding [RestorationScope].
  ///
  /// The child bucket obtained from the surrounding scope is made available to
  /// descendant widgets via [RestorationScope.of].
  ///
  /// If this is null, [RestorationScope.of] invoked by descendants will return
  /// null which effectively turns off state restoration for this subtree.
  final String? restorationId;

  @override
  State<RestorationScope> createState() => _RestorationScopeState();
}

class _RestorationScopeState extends State<RestorationScope> with RestorationMixin {
  @override
  String? get restorationId => widget.restorationId;

  @override
  void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
    // Nothing to do.
    // The bucket gets injected into the widget tree in the build method.
  }

  @override
  Widget build(BuildContext context) {
    return UnmanagedRestorationScope(
      bucket: bucket, // `bucket` is provided by the RestorationMixin.
      child: widget.child,
    );
  }
}

/// Inserts a provided [RestorationBucket] into the widget tree and makes it
/// available to descendants via [RestorationScope.of].
///
/// {@macro flutter.widgets.RestorationScope}
///
/// If [bucket] is null, no restoration bucket is made available to descendant
/// widgets ([RestorationScope.of] invoked from a descendant will return null).
/// This effectively turns off state restoration for the subtree because no
/// bucket for storing restoration data is made available.
///
/// See also:
///
///  * [RestorationScope], which inserts a bucket obtained from a surrounding
///    restoration scope into the widget tree and makes it accessible
///    for descendants via [RestorationScope.of].
///  * [RootRestorationScope], which inserts the root bucket provided by
///    the [RestorationManager] into the widget tree and makes it accessible
///    for descendants via [RestorationScope.of].
///  * [RestorationMixin], which may be used in [State] objects to manage the
///    restoration data of a [StatefulWidget] instead of manually interacting
///    with [RestorationScope]s and [RestorationBucket]s.
///  * [RestorationManager], which describes the basic concepts of state
///    restoration in Flutter.
class UnmanagedRestorationScope extends InheritedWidget {
  /// Creates an [UnmanagedRestorationScope].
  ///
  /// When [bucket] is null state restoration is turned off for the [child] and
  /// its descendants.
  ///
  /// The [child] must not be null.
  const UnmanagedRestorationScope({
    super.key,
    this.bucket,
    required super.child,
  }) : assert(child != null);

  /// The [RestorationBucket] that this widget will insert into the widget tree.
  ///
  /// Descendant widgets may obtain this bucket via [RestorationScope.of].
  final RestorationBucket? bucket;

  @override
  bool updateShouldNotify(UnmanagedRestorationScope oldWidget) {
    return oldWidget.bucket != bucket;
  }
}

/// Inserts a child bucket of [RestorationManager.rootBucket] into the widget
/// tree and makes it available to descendants via [RestorationScope.of].
///
/// This widget is usually used near the root of the widget tree to enable the
/// state restoration functionality for the application. For all other use
/// cases, consider using a regular [RestorationScope] instead.
///
/// The root restoration bucket can only be retrieved asynchronously from the
/// [RestorationManager]. To ensure that the provided [child] has its
/// restoration data available the first time it builds, the
/// [RootRestorationScope] will build an empty [Container] instead of the actual
/// [child] until the root bucket is available. To hide the empty container from
/// the eyes of users, the [RootRestorationScope] also delays rendering the
/// first frame while the container is shown. On platforms that show a splash
/// screen on app launch the splash screen is kept up (hiding the empty
/// container) until the bucket is available and the [child] is ready to be
/// build.
///
/// The exact behavior of this widget depends on its ancestors: When the
/// [RootRestorationScope] does not find an ancestor restoration bucket via
/// [RestorationScope.of] it will claim a child bucket from the root restoration
/// bucket ([RestorationManager.rootBucket]) using the provided [restorationId]
/// and inserts that bucket into the widget tree where descendants may access it
/// via [RestorationScope.of]. If the [RootRestorationScope] finds a non-null
/// ancestor restoration bucket via [RestorationScope.of] it will behave like a
/// regular [RestorationScope] instead: It will claim a child bucket from that
/// ancestor and insert that child into the widget tree.
///
/// Unlike the [RestorationScope] widget, the [RootRestorationScope] will
/// guarantee that descendants have a bucket available for storing restoration
/// data as long as [restorationId] is not null and [RestorationManager] is
/// able to provide a root bucket. In other words, it will force-enable
/// state restoration for the subtree if [restorationId] is not null.
///
/// If [restorationId] is null, no bucket is made available to descendants,
/// which effectively turns off state restoration for this subtree.
///
/// See also:
///
///  * [RestorationScope], which inserts a bucket obtained from a surrounding
///    restoration scope into the widget tree and makes it accessible
///    for descendants via [RestorationScope.of].
///  * [UnmanagedRestorationScope], which inserts a provided [RestorationBucket]
///    into the widget tree and makes it accessible for descendants via
///    [RestorationScope.of].
///  * [RestorationMixin], which may be used in [State] objects to manage the
///    restoration data of a [StatefulWidget] instead of manually interacting
///    with [RestorationScope]s and [RestorationBucket]s.
///  * [RestorationManager], which describes the basic concepts of state
///    restoration in Flutter.
class RootRestorationScope extends StatefulWidget {
  /// Creates a [RootRestorationScope].
  ///
  /// Providing null as the [restorationId] turns off state restoration for
  /// the [child] and its descendants.
  ///
  /// The [child] must not be null.
  const RootRestorationScope({
    super.key,
    required this.restorationId,
    required this.child,
  }) : assert(child != null);

  /// The widget below this widget in the tree.
  ///
  /// {@macro flutter.widgets.ProxyWidget.child}
  final Widget child;

  /// The restoration ID used to identify the child bucket that this widget
  /// will insert into the tree.
  ///
  /// If this is null, no bucket is made available to descendants and state
  /// restoration for the subtree is essentially turned off.
  final String? restorationId;

  @override
  State<RootRestorationScope> createState() => _RootRestorationScopeState();
}

class _RootRestorationScopeState extends State<RootRestorationScope> {
  bool? _okToRenderBlankContainer;
  bool _rootBucketValid = false;
  RestorationBucket? _rootBucket;
  RestorationBucket? _ancestorBucket;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _ancestorBucket = RestorationScope.of(context);
    _loadRootBucketIfNecessary();
    _okToRenderBlankContainer ??= widget.restorationId != null && _needsRootBucketInserted;
  }

  @override
  void didUpdateWidget(RootRestorationScope oldWidget) {
    super.didUpdateWidget(oldWidget);
    _loadRootBucketIfNecessary();
  }

  bool get _needsRootBucketInserted => _ancestorBucket == null;

  bool get _isWaitingForRootBucket {
    return widget.restorationId != null && _needsRootBucketInserted && !_rootBucketValid;
  }

  bool _isLoadingRootBucket = false;

  void _loadRootBucketIfNecessary() {
    if (_isWaitingForRootBucket && !_isLoadingRootBucket) {
      _isLoadingRootBucket = true;
      RendererBinding.instance.deferFirstFrame();
      ServicesBinding.instance.restorationManager.rootBucket.then((RestorationBucket? bucket) {
        _isLoadingRootBucket = false;
        if (mounted) {
          ServicesBinding.instance.restorationManager.addListener(_replaceRootBucket);
          setState(() {
            _rootBucket = bucket;
            _rootBucketValid = true;
            _okToRenderBlankContainer = false;
          });
        }
        RendererBinding.instance.allowFirstFrame();
      });
    }
  }

  void _replaceRootBucket() {
    _rootBucketValid = false;
    _rootBucket = null;
    ServicesBinding.instance.restorationManager.removeListener(_replaceRootBucket);
    _loadRootBucketIfNecessary();
    assert(!_isWaitingForRootBucket); // Ensure that load finished synchronously.
  }

  @override
  void dispose() {
    if (_rootBucketValid) {
      ServicesBinding.instance.restorationManager.removeListener(_replaceRootBucket);
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (_okToRenderBlankContainer! && _isWaitingForRootBucket) {
      return const SizedBox.shrink();
    }

    return UnmanagedRestorationScope(
      bucket: _ancestorBucket ?? _rootBucket,
      child: RestorationScope(
        restorationId: widget.restorationId,
        child: widget.child,
      ),
    );
  }
}

/// Manages an object of type `T`, whose value a [State] object wants to have
/// restored during state restoration.
///
/// The property wraps an object of type `T`. It knows how to store its value in
/// the restoration data and it knows how to re-instantiate that object from the
/// information it previously stored in the restoration data.
///
/// The knowledge of how to store the wrapped object in the restoration data is
/// encoded in the [toPrimitives] method and the knowledge of how to
/// re-instantiate the object from that data is encoded in the [fromPrimitives]
/// method. A call to [toPrimitives] must return a representation of the wrapped
/// object that can be serialized with the [StandardMessageCodec]. If any
/// collections (e.g. [List]s, [Map]s, etc.) are returned, they must not be
/// modified after they have been returned from [toPrimitives]. At a later point
/// in time (which may be after the application restarted), the data obtained
/// from [toPrimitives] may be handed back to the property's [fromPrimitives]
/// method to restore it to the previous state described by that data.
///
/// A [RestorableProperty] needs to be registered to a [RestorationMixin] using
/// a restoration ID that is unique within the mixin. The [RestorationMixin]
/// provides and manages the [RestorationBucket], in which the data returned by
/// [toPrimitives] is stored.
///
/// Whenever the value returned by [toPrimitives] (or the [enabled] getter)
/// changes, the [RestorableProperty] must call [notifyListeners]. This will
/// trigger the [RestorationMixin] to update the data it has stored for the
/// property in its [RestorationBucket] to the latest information returned by
/// [toPrimitives].
///
/// When the property is registered with the [RestorationMixin], the mixin
/// checks whether there is any restoration data available for the property. If
/// data is available, the mixin calls [fromPrimitives] on the property, which
/// must return an object that matches the object the property wrapped when the
/// provided restoration data was obtained from [toPrimitives]. If no
/// restoration data is available to restore the property's wrapped object from,
/// the mixin calls [createDefaultValue]. The value returned by either of those
/// methods is then handed to the property's [initWithValue] method.
///
/// Usually, subclasses of [RestorableProperty] hold on to the value provided to
/// them in [initWithValue] and make it accessible to the [State] object that
/// owns the property. This [RestorableProperty] base class, however, has no
/// opinion about what to do with the value provided to [initWithValue].
///
/// The [RestorationMixin] may call [fromPrimitives]/[createDefaultValue]
/// followed by [initWithValue] multiple times throughout the life of a
/// [RestorableProperty]: Whenever new restoration data is made available to the
/// [RestorationMixin] the property is registered with, the cycle of calling
/// [fromPrimitives] (if the new restoration data contains information to
/// restore the property from) or [createDefaultValue] (if no information for
/// the property is available in the new restoration data) followed by a call to
/// [initWithValue] repeats. Whenever [initWithValue] is called, the property
/// should forget the old value it was wrapping and re-initialize itself with
/// the newly provided value.
///
/// In a typical use case, a subclass of [RestorableProperty] is instantiated
/// either to initialize a member variable of a [State] object or within
/// [State.initState]. It is then registered to a [RestorationMixin] in
/// [RestorationMixin.restoreState] and later [dispose]ed in [State.dispose].
/// For less common use cases (e.g. if the value stored in a
/// [RestorableProperty] is only needed while the [State] object is in a certain
/// state), a [RestorableProperty] may be registered with a [RestorationMixin]
/// any time after [RestorationMixin.restoreState] has been called for the first
/// time. A [RestorableProperty] may also be unregistered from a
/// [RestorationMixin] before the owning [State] object is disposed by calling
/// [RestorationMixin.unregisterFromRestoration]. This is uncommon, though, and
/// will delete the information that the property contributed from the
/// restoration data (meaning the value of the property will no longer be
/// restored during a future state restoration).
///
/// See also:
///
///  * [RestorableValue], which is a [RestorableProperty] that makes the wrapped
///    value accessible to the owning [State] object via a `value`
///    getter and setter.
///  * [RestorationMixin], to which a [RestorableProperty] must be registered.
///  * [RestorationManager], which describes how state restoration works in
///    Flutter.
abstract class RestorableProperty<T> extends ChangeNotifier {
  /// Called by the [RestorationMixin] if no restoration data is available to
  /// restore the value of the property from to obtain the default value for the
  /// property.
  ///
  /// The method returns the default value that the property should wrap if no
  /// restoration data is available. After this is called, [initWithValue] will
  /// be called with this method's return value.
  ///
  /// The method may be called multiple times throughout the life of the
  /// [RestorableProperty]. Whenever new restoration data has been provided to
  /// the [RestorationMixin] the property is registered to, either this method
  /// or [fromPrimitives] is called before [initWithValue] is invoked.
  T createDefaultValue();

  /// Called by the [RestorationMixin] to convert the `data` previously
  /// retrieved from [toPrimitives] back into an object of type `T` that this
  /// property should wrap.
  ///
  /// The object returned by this method is passed to [initWithValue] to restore
  /// the value that this property is wrapping to the value described by the
  /// provided `data`.
  ///
  /// The method may be called multiple times throughout the life of the
  /// [RestorableProperty]. Whenever new restoration data has been provided to
  /// the [RestorationMixin] the property is registered to, either this method
  /// or [createDefaultValue] is called before [initWithValue] is invoked.
  T fromPrimitives(Object? data);

  /// Called by the [RestorationMixin] with the `value` returned by either
  /// [createDefaultValue] or [fromPrimitives] to set the value that this
  /// property currently wraps.
  ///
  /// The [initWithValue] method may be called multiple times throughout the
  /// life of the [RestorableProperty] whenever new restoration data has been
  /// provided to the [RestorationMixin] the property is registered to. When
  /// [initWithValue] is called, the property should forget its previous value
  /// and re-initialize itself to the newly provided `value`.
  void initWithValue(T value);

  /// Called by the [RestorationMixin] to retrieve the information that this
  /// property wants to store in the restoration data.
  ///
  /// The returned object must be serializable with the [StandardMessageCodec]
  /// and if it includes any collections, those should not be modified after
  /// they have been returned by this method.
  ///
  /// The information returned by this method may be handed back to the property
  /// in a call to [fromPrimitives] at a later point in time (possibly after the
  /// application restarted) to restore the value that the property is currently
  /// wrapping.
  ///
  /// When the value returned by this method changes, the property must call
  /// [notifyListeners]. The [RestorationMixin] will invoke this method whenever
  /// the property's listeners are notified.
  Object? toPrimitives();

  /// Whether the object currently returned by [toPrimitives] should be included
  /// in the restoration state.
  ///
  /// When this returns false, no information is included in the restoration
  /// data for this property and the property will be initialized to its default
  /// value (obtained from [createDefaultValue]) the next time that restoration
  /// data is used for state restoration.
  ///
  /// Whenever the value returned by this getter changes, [notifyListeners] must
  /// be called. When the value changes from true to false, the information last
  /// retrieved from [toPrimitives] is removed from the restoration data. When
  /// it changes from false to true, [toPrimitives] is invoked to add the latest
  /// restoration information provided by this property to the restoration data.
  bool get enabled => true;

  bool _disposed = false;

  @override
  void dispose() {
    assert(ChangeNotifier.debugAssertNotDisposed(this)); // FYI, This uses ChangeNotifier's _debugDisposed, not _disposed.
    _owner?._unregister(this);
    super.dispose();
    _disposed = true;
  }

  // ID under which the property has been registered with the RestorationMixin.
  String? _restorationId;
  RestorationMixin? _owner;
  void _register(String restorationId, RestorationMixin owner) {
    assert(ChangeNotifier.debugAssertNotDisposed(this));
    assert(restorationId != null);
    assert(owner != null);
    _restorationId = restorationId;
    _owner = owner;
  }
  void _unregister() {
    assert(ChangeNotifier.debugAssertNotDisposed(this));
    assert(_restorationId != null);
    assert(_owner != null);
    _restorationId = null;
    _owner = null;
  }

  /// The [State] object that this property is registered with.
  ///
  /// Must only be called when [isRegistered] is true.
  @protected
  State get state {
    assert(isRegistered);
    assert(ChangeNotifier.debugAssertNotDisposed(this));
    return _owner!;
  }

  /// Whether this property is currently registered with a [RestorationMixin].
  @protected
  bool get isRegistered {
    assert(ChangeNotifier.debugAssertNotDisposed(this));
    return _restorationId != null;
  }
}

/// Manages the restoration data for a [State] object of a [StatefulWidget].
///
/// Restoration data can be serialized out and, at a later point in time, be
/// used to restore the stateful members in the [State] object to the same
/// values they had when the data was generated.
///
/// This mixin organizes the restoration data of a [State] object in
/// [RestorableProperty]. All the information that the [State] object wants to
/// get restored during state restoration need to be saved in a subclass of
/// [RestorableProperty]. For example, to restore the count value in a counter
/// app, that value should be stored in a member variable of type
/// [RestorableInt] instead of a plain member variable of type [int].
///
/// The mixin ensures that the current values of the [RestorableProperty]s are
/// serialized as part of the restoration state. It is up to the [State] to
/// ensure that the data stored in the properties is always up to date. When the
/// widget is restored from previously generated restoration data, the values of
/// the [RestorableProperty]s are automatically restored to the values that had
/// when the restoration data was serialized out.
///
/// Within a [State] that uses this mixin, [RestorableProperty]s are usually
/// instantiated to initialize member variables. Users of the mixin must
/// override [restoreState] and register their previously instantiated
/// [RestorableProperty]s in this method by calling [registerForRestoration].
/// The mixin calls this method for the first time right after
/// [State.initState]. After registration, the values stored in the property
/// have either been restored to their previous value or - if no restoration
/// data for restoring is available - they are initialized with a
/// property-specific default value. At the end of a [State] object's life
/// cycle, all restorable properties must be disposed in [State.dispose].
///
/// In addition to being invoked right after [State.initState], [restoreState]
/// is invoked again when new restoration data has been provided to the mixin.
/// When this happens, the [State] object must re-register all properties with
/// [registerForRestoration] again to restore them to their previous values as
/// described by the new restoration data. All initialization logic that depends
/// on the current value of a restorable property should be included in the
/// [restoreState] method to ensure it re-executes when the properties are
/// restored to a different value during the life time of the [State] object.
///
/// Internally, the mixin stores the restoration data from all registered
/// properties in a [RestorationBucket] claimed from the surrounding
/// [RestorationScope] using the [State]-provided [restorationId]. The
/// [restorationId] must be unique in the surrounding [RestorationScope]. State
/// restoration is disabled for the [State] object using this mixin if
/// [restorationId] is null or when there is no surrounding [RestorationScope].
/// In that case, the values of the registered properties will not be restored
/// during state restoration.
///
/// The [RestorationBucket] used to store the registered properties is available
/// via the [bucket] getter. Interacting directly with the bucket is uncommon,
/// but the [State] object may make this bucket available for its descendants to
/// claim child buckets from. For that, the [bucket] is injected into the widget
/// tree in [State.build] with the help of an [UnmanagedRestorationScope].
///
/// The [bucket] getter returns null if state restoration is turned off. If
/// state restoration is turned on or off during the lifetime of the widget
/// (e.g. because [restorationId] changes from null to non-null) the value
/// returned by the getter will also change from null to non-null or vice versa.
/// The mixin calls [didToggleBucket] on itself to notify the [State] object
/// about this change. Overriding this method is not necessary as long as the
/// [State] object does not directly interact with the [bucket].
///
/// Whenever the value returned by [restorationId] changes,
/// [didUpdateRestorationId] must be called (unless the change already triggers
/// a call to [didUpdateWidget]).
///
/// {@tool dartpad}
/// This example demonstrates how to make a simple counter app restorable by
/// using the [RestorationMixin] and a [RestorableInt].
///
/// ** See code in examples/api/lib/widgets/restoration/restoration_mixin.0.dart **
/// {@end-tool}
///
/// See also:
///
///  * [RestorableProperty], which is the base class for all restoration
///    properties managed by this mixin.
///  * [RestorationManager], which describes how state restoration in Flutter
///    works.
///  * [RestorationScope], which creates a new namespace for restoration IDs
///    in the widget tree.
@optionalTypeArgs
mixin RestorationMixin<S extends StatefulWidget> on State<S> {
  /// The restoration ID used for the [RestorationBucket] in which the mixin
  /// will store the restoration data of all registered properties.
  ///
  /// The restoration ID is used to claim a child [RestorationScope] from the
  /// surrounding [RestorationScope] (accessed via [RestorationScope.of]) and
  /// the ID must be unique in that scope (otherwise an exception is triggered
  /// in debug mode).
  ///
  /// State restoration for this mixin is turned off when this getter returns
  /// null or when there is no surrounding [RestorationScope] available. When
  /// state restoration is turned off, the values of the registered properties
  /// cannot be restored.
  ///
  /// Whenever the value returned by this getter changes,
  /// [didUpdateRestorationId] must be called unless the (unless the change
  /// already triggered a call to [didUpdateWidget]).
  ///
  /// The restoration ID returned by this getter is often provided in the
  /// constructor of the [StatefulWidget] that this [State] object is associated
  /// with.
  @protected
  String? get restorationId;

  /// The [RestorationBucket] used for the restoration data of the
  /// [RestorableProperty]s registered to this mixin.
  ///
  /// The bucket has been claimed from the surrounding [RestorationScope] using
  /// [restorationId].
  ///
  /// The getter returns null if state restoration is turned off. When state
  /// restoration is turned on or off during the lifetime of this mixin (and
  /// hence the return value of this getter switches between null and non-null)
  /// [didToggleBucket] is called.
  ///
  /// Interacting directly with this bucket is uncommon. However, the bucket may
  /// be injected into the widget tree in the [State]'s `build` method using an
  /// [UnmanagedRestorationScope]. That allows descendants to claim child
  /// buckets from this bucket for their own restoration needs.
  RestorationBucket? get bucket => _bucket;
  RestorationBucket? _bucket;

  /// Called to initialize or restore the [RestorableProperty]s used by the
  /// [State] object.
  ///
  /// This method is always invoked at least once right after [State.initState]
  /// to register the [RestorableProperty]s with the mixin even when state
  /// restoration is turned off or no restoration data is available for this
  /// [State] object.
  ///
  /// Typically, [registerForRestoration] is called from this method to register
  /// all [RestorableProperty]s used by the [State] object with the mixin. The
  /// registration will either restore the property's value to the value
  /// described by the restoration data, if available, or, if no restoration
  /// data is available - initialize it to a property-specific default value.
  ///
  /// The method is called again whenever new restoration data (in the form of a
  /// new [bucket]) has been provided to the mixin. When that happens, the
  /// [State] object must re-register all previously registered properties,
  /// which will restore their values to the value described by the new
  /// restoration data.
  ///
  /// Since the method may change the value of the registered properties when
  /// new restoration state is provided, all initialization logic that depends
  /// on a specific value of a [RestorableProperty] should be included in this
  /// method. That way, that logic re-executes when the [RestorableProperty]s
  /// have their values restored from newly provided restoration data.
  ///
  /// The first time the method is invoked, the provided `oldBucket` argument is
  /// always null. In subsequent calls triggered by new restoration data in the
  /// form of a new bucket, the argument given is the previous value of
  /// [bucket].
  @mustCallSuper
  @protected
  void restoreState(RestorationBucket? oldBucket, bool initialRestore);

  /// Called when [bucket] switches between null and non-null values.
  ///
  /// [State] objects that wish to directly interact with the bucket may
  /// override this method to store additional values in the bucket when one
  /// becomes available or to save values stored in a bucket elsewhere when the
  /// bucket goes away. This is uncommon and storing those values in
  /// [RestorableProperty]s should be considered instead.
  ///
  /// The `oldBucket` is provided to the method when the [bucket] getter changes
  /// from non-null to null. The `oldBucket` argument is null when the [bucket]
  /// changes from null to non-null.
  ///
  /// See also:
  ///
  ///  * [restoreState], which is called when the [bucket] changes from one
  ///    non-null value to another non-null value.
  @mustCallSuper
  @protected
  void didToggleBucket(RestorationBucket? oldBucket) {
    // When a bucket is replaced, must `restoreState` is called instead.
    assert(_bucket?.isReplacing != true);
  }

  // Maps properties to their listeners.
  final Map<RestorableProperty<Object?>, VoidCallback> _properties = <RestorableProperty<Object?>, VoidCallback>{};

  /// Registers a [RestorableProperty] for state restoration.
  ///
  /// The registration associates the provided `property` with the provided
  /// `restorationId`. If restoration data is available for the provided
  /// `restorationId`, the property's value is restored to the value described
  /// by the restoration data. If no restoration data is available, the property
  /// will be initialized to a property-specific default value.
  ///
  /// Each property within a [State] object must be registered under a unique
  /// ID. Only registered properties will have their values restored during
  /// state restoration.
  ///
  /// Typically, this method is called from within [restoreState] to register
  /// all restorable properties of the owning [State] object. However, if a
  /// given [RestorableProperty] is only needed when certain conditions are met
  /// within the [State], [registerForRestoration] may also be called at any
  /// time after [restoreState] has been invoked for the first time.
  ///
  /// A property that has been registered outside of [restoreState] must be
  /// re-registered within [restoreState] the next time that method is called
  /// unless it has been unregistered with [unregisterFromRestoration].
  @protected
  void registerForRestoration(RestorableProperty<Object?> property, String restorationId) {
    assert(property != null);
    assert(restorationId != null);
    assert(property._restorationId == null || (_debugDoingRestore && property._restorationId == restorationId),
           'Property is already registered under ${property._restorationId}.',
    );
    assert(_debugDoingRestore || !_properties.keys.map((RestorableProperty<Object?> r) => r._restorationId).contains(restorationId),
           '"$restorationId" is already registered to another property.',
    );
    final bool hasSerializedValue = bucket?.contains(restorationId) ?? false;
    final Object? initialValue = hasSerializedValue
        ? property.fromPrimitives(bucket!.read<Object>(restorationId))
        : property.createDefaultValue();

    if (!property.isRegistered) {
      property._register(restorationId, this);
      void listener() {
        if (bucket == null) {
          return;
        }
        _updateProperty(property);
      }
      property.addListener(listener);
      _properties[property] = listener;
    }

    assert(
      property._restorationId == restorationId &&
      property._owner == this &&
      _properties.containsKey(property),
    );

    property.initWithValue(initialValue);
    if (!hasSerializedValue && property.enabled && bucket != null) {
      _updateProperty(property);
    }

    assert(() {
      _debugPropertiesWaitingForReregistration?.remove(property);
      return true;
    }());
  }

  /// Unregisters a [RestorableProperty] from state restoration.
  ///
  /// The value of the `property` is removed from the restoration data and it
  /// will not be restored if that data is used in a future state restoration.
  ///
  /// Calling this method is uncommon, but may be necessary if the data of a
  /// [RestorableProperty] is only relevant when the [State] object is in a
  /// certain state. When the data of a property is no longer necessary to
  /// restore the internal state of a [State] object, it may be removed from the
  /// restoration data by calling this method.
  @protected
  void unregisterFromRestoration(RestorableProperty<Object?> property) {
    assert(property != null);
    assert(property._owner == this);
    _bucket?.remove<Object?>(property._restorationId!);
    _unregister(property);
  }

  /// Must be called when the value returned by [restorationId] changes.
  ///
  /// This method is automatically called from [didUpdateWidget]. Therefore,
  /// manually invoking this method may be omitted when the change in
  /// [restorationId] was caused by an updated widget.
  @protected
  void didUpdateRestorationId() {
    // There's nothing to do if:
    //  - We don't have a parent to claim a bucket from.
    //  - Our current bucket already uses the provided restoration ID.
    //  - There's a restore pending, which means that didChangeDependencies
    //    will be called and we handle the rename there.
    if (_currentParent == null || _bucket?.restorationId == restorationId || restorePending) {
      return;
    }

    final RestorationBucket? oldBucket = _bucket;
    assert(!restorePending);
    final bool didReplaceBucket = _updateBucketIfNecessary(parent: _currentParent, restorePending: false);
    if (didReplaceBucket) {
      assert(oldBucket != _bucket);
      assert(_bucket == null || oldBucket == null);
      oldBucket?.dispose();
    }
  }

  @override
  void didUpdateWidget(S oldWidget) {
    super.didUpdateWidget(oldWidget);
    didUpdateRestorationId();
  }

  /// Whether [restoreState] will be called at the beginning of the next build
  /// phase.
  ///
  /// Returns true when new restoration data has been provided to the mixin, but
  /// the registered [RestorableProperty]s have not been restored to their new
  /// values (as described by the new restoration data) yet. The properties will
  /// get the values restored when [restoreState] is invoked at the beginning of
  /// the next build cycle.
  ///
  /// While this is true, [bucket] will also still return the old bucket with
  /// the old restoration data. It will update to the new bucket with the new
  /// data just before [restoreState] is invoked.
  bool get restorePending {
    if (_firstRestorePending) {
      return true;
    }
    if (restorationId == null) {
      return false;
    }
    final RestorationBucket? potentialNewParent = RestorationScope.of(context);
    return potentialNewParent != _currentParent && (potentialNewParent?.isReplacing ?? false);
  }

  List<RestorableProperty<Object?>>? _debugPropertiesWaitingForReregistration;
  bool get _debugDoingRestore => _debugPropertiesWaitingForReregistration != null;

  bool _firstRestorePending = true;
  RestorationBucket? _currentParent;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    final RestorationBucket? oldBucket = _bucket;
    final bool needsRestore = restorePending;
    _currentParent = RestorationScope.of(context);

    final bool didReplaceBucket = _updateBucketIfNecessary(parent: _currentParent, restorePending: needsRestore);

    if (needsRestore) {
      _doRestore(oldBucket);
    }
    if (didReplaceBucket) {
      assert(oldBucket != _bucket);
      oldBucket?.dispose();
    }
  }

  void _doRestore(RestorationBucket? oldBucket) {
    assert(() {
      _debugPropertiesWaitingForReregistration = _properties.keys.toList();
      return true;
    }());

    restoreState(oldBucket, _firstRestorePending);
    _firstRestorePending = false;

    assert(() {
      if (_debugPropertiesWaitingForReregistration!.isNotEmpty) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary(
            'Previously registered RestorableProperties must be re-registered in "restoreState".',
          ),
          ErrorDescription(
            'The RestorableProperties with the following IDs were not re-registered to $this when '
                '"restoreState" was called:',
          ),
          ..._debugPropertiesWaitingForReregistration!.map((RestorableProperty<Object?> property) => ErrorDescription(
            ' * ${property._restorationId}',
          )),
        ]);
      }
      _debugPropertiesWaitingForReregistration = null;
      return true;
    }());
  }

  // Returns true if `bucket` has been replaced with a new bucket. It's the
  // responsibility of the caller to dispose the old bucket when this returns true.
  bool _updateBucketIfNecessary({
    required RestorationBucket? parent,
    required bool restorePending,
  }) {
    if (restorationId == null || parent == null) {
      final bool didReplace = _setNewBucketIfNecessary(newBucket: null, restorePending: restorePending);
      assert(_bucket == null);
      return didReplace;
    }
    assert(restorationId != null);
    assert(parent != null);
    if (restorePending || _bucket == null) {
      final RestorationBucket newBucket = parent.claimChild(restorationId!, debugOwner: this);
      assert(newBucket != null);
      final bool didReplace = _setNewBucketIfNecessary(newBucket: newBucket, restorePending: restorePending);
      assert(_bucket == newBucket);
      return didReplace;
    }
    // We have an existing bucket, make sure it has the right parent and id.
    assert(_bucket != null);
    assert(!restorePending);
    _bucket!.rename(restorationId!);
    parent.adoptChild(_bucket!);
    return false;
  }

  // Returns true if `bucket` has been replaced with a new bucket. It's the
  // responsibility of the caller to dispose the old bucket when this returns true.
  bool _setNewBucketIfNecessary({required RestorationBucket? newBucket, required bool restorePending}) {
    if (newBucket == _bucket) {
      return false;
    }
    final RestorationBucket? oldBucket = _bucket;
    _bucket = newBucket;
    if (!restorePending) {
      // Write the current property values into the new bucket to persist them.
      if (_bucket != null) {
        _properties.keys.forEach(_updateProperty);
      }
      didToggleBucket(oldBucket);
    }
    return true;
  }

  void _updateProperty(RestorableProperty<Object?> property) {
    if (property.enabled) {
      _bucket?.write(property._restorationId!, property.toPrimitives());
    } else {
      _bucket?.remove<Object>(property._restorationId!);
    }
  }

  void _unregister(RestorableProperty<Object?> property) {
    final VoidCallback listener = _properties.remove(property)!;
    assert(() {
      _debugPropertiesWaitingForReregistration?.remove(property);
      return true;
    }());
    property.removeListener(listener);
    property._unregister();
  }

  @override
  void dispose() {
    _properties.forEach((RestorableProperty<Object?> property, VoidCallback listener) {
      if (!property._disposed) {
        property.removeListener(listener);
      }
    });
    _bucket?.dispose();
    _bucket = null;
    super.dispose();
  }
}
