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

import 'basic.dart';
import 'framework.dart';
import 'scroll_controller.dart';
import 'scroll_physics.dart';
import 'scroll_view.dart';
import 'sliver.dart';
import 'ticker_provider.dart';

/// Signature for the builder callback used by [AnimatedList].
typedef AnimatedListItemBuilder = Widget Function(BuildContext context, int index, Animation<double> animation);

/// Signature for the builder callback used by [AnimatedListState.removeItem].
typedef AnimatedListRemovedItemBuilder = Widget Function(BuildContext context, Animation<double> animation);

// The default insert/remove animation duration.
const Duration _kDuration = Duration(milliseconds: 300);

// Incoming and outgoing AnimatedList items.
class _ActiveItem implements Comparable<_ActiveItem> {
  _ActiveItem.incoming(this.controller, this.itemIndex) : removedItemBuilder = null;
  _ActiveItem.outgoing(this.controller, this.itemIndex, this.removedItemBuilder);
  _ActiveItem.index(this.itemIndex)
    : controller = null,
      removedItemBuilder = null;

  final AnimationController? controller;
  final AnimatedListRemovedItemBuilder? removedItemBuilder;
  int itemIndex;

  @override
  int compareTo(_ActiveItem other) => itemIndex - other.itemIndex;
}

/// A scrolling container that animates items when they are inserted or removed.
///
/// This widget's [AnimatedListState] can be used to dynamically insert or
/// remove items. To refer to the [AnimatedListState] either provide a
/// [GlobalKey] or use the static [of] method from an item's input callback.
///
/// This widget is similar to one created by [ListView.builder].
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=ZtfItHwFlZ8}
///
/// {@tool dartpad --template=freeform}
/// This sample application uses an [AnimatedList] to create an effect when
/// items are removed or added to the list.
///
/// ```dart imports
/// import 'package:flutter/foundation.dart';
/// import 'package:flutter/material.dart';
/// ```
///
/// ```dart
/// class AnimatedListSample extends StatefulWidget {
///   @override
///   _AnimatedListSampleState createState() => _AnimatedListSampleState();
/// }
///
/// class _AnimatedListSampleState extends State<AnimatedListSample> {
///   final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
///   ListModel<int> _list;
///   int _selectedItem;
///   int _nextItem; // The next item inserted when the user presses the '+' button.
///
///   @override
///   void initState() {
///     super.initState();
///     _list = ListModel<int>(
///       listKey: _listKey,
///       initialItems: <int>[0, 1, 2],
///       removedItemBuilder: _buildRemovedItem,
///     );
///     _nextItem = 3;
///   }
///
///   // Used to build list items that haven't been removed.
///   Widget _buildItem(BuildContext context, int index, Animation<double> animation) {
///     return CardItem(
///       animation: animation,
///       item: _list[index],
///       selected: _selectedItem == _list[index],
///       onTap: () {
///         setState(() {
///           _selectedItem = _selectedItem == _list[index] ? null : _list[index];
///         });
///       },
///     );
///   }
///
///   // Used to build an item after it has been removed from the list. This
///   // method is needed because a removed item remains visible until its
///   // animation has completed (even though it's gone as far this ListModel is
///   // concerned). The widget will be used by the
///   // [AnimatedListState.removeItem] method's
///   // [AnimatedListRemovedItemBuilder] parameter.
///   Widget _buildRemovedItem(int item, BuildContext context, Animation<double> animation) {
///     return CardItem(
///       animation: animation,
///       item: item,
///       selected: false,
///       // No gesture detector here: we don't want removed items to be interactive.
///     );
///   }
///
///   // Insert the "next item" into the list model.
///   void _insert() {
///     final int index = _selectedItem == null ? _list.length : _list.indexOf(_selectedItem);
///     _list.insert(index, _nextItem++);
///   }
///
///   // Remove the selected item from the list model.
///   void _remove() {
///     if (_selectedItem != null) {
///       _list.removeAt(_list.indexOf(_selectedItem));
///       setState(() {
///         _selectedItem = null;
///       });
///     }
///   }
///
///   @override
///   Widget build(BuildContext context) {
///     return MaterialApp(
///       home: Scaffold(
///         appBar: AppBar(
///           title: const Text('AnimatedList'),
///           actions: <Widget>[
///             IconButton(
///               icon: const Icon(Icons.add_circle),
///               onPressed: _insert,
///               tooltip: 'insert a new item',
///             ),
///             IconButton(
///               icon: const Icon(Icons.remove_circle),
///               onPressed: _remove,
///               tooltip: 'remove the selected item',
///             ),
///           ],
///         ),
///         body: Padding(
///           padding: const EdgeInsets.all(16.0),
///           child: AnimatedList(
///             key: _listKey,
///             initialItemCount: _list.length,
///             itemBuilder: _buildItem,
///           ),
///         ),
///       ),
///     );
///   }
/// }
///
/// /// Keeps a Dart [List] in sync with an [AnimatedList].
/// ///
/// /// The [insert] and [removeAt] methods apply to both the internal list and
/// /// the animated list that belongs to [listKey].
/// ///
/// /// This class only exposes as much of the Dart List API as is needed by the
/// /// sample app. More list methods are easily added, however methods that
/// /// mutate the list must make the same changes to the animated list in terms
/// /// of [AnimatedListState.insertItem] and [AnimatedList.removeItem].
/// class ListModel<E> {
///   ListModel({
///     @required this.listKey,
///     @required this.removedItemBuilder,
///     Iterable<E> initialItems,
///   }) : assert(listKey != null),
///       assert(removedItemBuilder != null),
///       _items = List<E>.from(initialItems ?? <E>[]);
///
///   final GlobalKey<AnimatedListState> listKey;
///   final dynamic removedItemBuilder;
///   final List<E> _items;
///
///   AnimatedListState get _animatedList => listKey.currentState;
///
///   void insert(int index, E item) {
///     _items.insert(index, item);
///     _animatedList.insertItem(index);
///   }
///
///   E removeAt(int index) {
///     final E removedItem = _items.removeAt(index);
///     if (removedItem != null) {
///       _animatedList.removeItem(
///         index,
///           (BuildContext context, Animation<double> animation) => removedItemBuilder(removedItem, context, animation),
///       );
///     }
///     return removedItem;
///   }
///
///   int get length => _items.length;
///
///   E operator [](int index) => _items[index];
///
///   int indexOf(E item) => _items.indexOf(item);
/// }
///
/// /// Displays its integer item as 'item N' on a Card whose color is based on
/// /// the item's value.
/// ///
/// /// The text is displayed in bright green if [selected] is
/// /// true. This widget's height is based on the [animation] parameter, it
/// /// varies from 0 to 128 as the animation varies from 0.0 to 1.0.
/// class CardItem extends StatelessWidget {
///   const CardItem({
///     Key key,
///     @required this.animation,
///     this.onTap,
///     @required this.item,
///     this.selected: false
///   }) : assert(animation != null),
///        assert(item != null && item >= 0),
///        assert(selected != null),
///        super(key: key);
///
///   final Animation<double> animation;
///   final VoidCallback onTap;
///   final int item;
///   final bool selected;
///
///   @override
///   Widget build(BuildContext context) {
///     TextStyle textStyle = Theme.of(context).textTheme.headline4;
///     if (selected)
///       textStyle = textStyle.copyWith(color: Colors.lightGreenAccent[400]);
///     return Padding(
///       padding: const EdgeInsets.all(2.0),
///       child: SizeTransition(
///         axis: Axis.vertical,
///         sizeFactor: animation,
///         child: GestureDetector(
///           behavior: HitTestBehavior.opaque,
///           onTap: onTap,
///           child: SizedBox(
///             height: 80.0,
///             child: Card(
///               color: Colors.primaries[item % Colors.primaries.length],
///               child: Center(
///                 child: Text('Item $item', style: textStyle),
///               ),
///             ),
///           ),
///         ),
///       ),
///     );
///   }
/// }
///
/// void main() {
///   runApp(AnimatedListSample());
/// }
/// ```
/// {@end-tool}
///
/// See also:
///
///  * [SliverAnimatedList], a sliver that animates items when they are inserted
///    or removed from a list.
class AnimatedList extends StatefulWidget {
  /// Creates a scrolling container that animates items when they are inserted
  /// or removed.
  const AnimatedList({
    Key? key,
    required this.itemBuilder,
    this.initialItemCount = 0,
    this.scrollDirection = Axis.vertical,
    this.reverse = false,
    this.controller,
    this.primary,
    this.physics,
    this.shrinkWrap = false,
    this.padding,
  }) : assert(itemBuilder != null),
       assert(initialItemCount != null && initialItemCount >= 0),
       super(key: key);

  /// Called, as needed, to build list item widgets.
  ///
  /// List items are only built when they're scrolled into view.
  ///
  /// The [AnimatedListItemBuilder] index parameter indicates the item's
  /// position in the list. The value of the index parameter will be between 0
  /// and [initialItemCount] plus the total number of items that have been
  /// inserted with [AnimatedListState.insertItem] and less the total number of
  /// items that have been removed with [AnimatedListState.removeItem].
  ///
  /// Implementations of this callback should assume that
  /// [AnimatedListState.removeItem] removes an item immediately.
  final AnimatedListItemBuilder itemBuilder;

  /// {@template flutter.widgets.animatedList.initialItemCount}
  /// The number of items the list will start with.
  ///
  /// The appearance of the initial items is not animated. They
  /// are created, as needed, by [itemBuilder] with an animation parameter
  /// of [kAlwaysCompleteAnimation].
  /// {@endtemplate}
  final int initialItemCount;

  /// The axis along which the scroll view scrolls.
  ///
  /// Defaults to [Axis.vertical].
  final Axis scrollDirection;

  /// Whether the scroll view scrolls in the reading direction.
  ///
  /// For example, if the reading direction is left-to-right and
  /// [scrollDirection] is [Axis.horizontal], then the scroll view scrolls from
  /// left to right when [reverse] is false and from right to left when
  /// [reverse] is true.
  ///
  /// Similarly, if [scrollDirection] is [Axis.vertical], then the scroll view
  /// scrolls from top to bottom when [reverse] is false and from bottom to top
  /// when [reverse] is true.
  ///
  /// Defaults to false.
  final bool reverse;

  /// An object that can be used to control the position to which this scroll
  /// view is scrolled.
  ///
  /// Must be null if [primary] is true.
  ///
  /// A [ScrollController] serves several purposes. It can be used to control
  /// the initial scroll position (see [ScrollController.initialScrollOffset]).
  /// It can be used to control whether the scroll view should automatically
  /// save and restore its scroll position in the [PageStorage] (see
  /// [ScrollController.keepScrollOffset]). It can be used to read the current
  /// scroll position (see [ScrollController.offset]), or change it (see
  /// [ScrollController.animateTo]).
  final ScrollController? controller;

  /// Whether this is the primary scroll view associated with the parent
  /// [PrimaryScrollController].
  ///
  /// On iOS, this identifies the scroll view that will scroll to top in
  /// response to a tap in the status bar.
  ///
  /// Defaults to true when [scrollDirection] is [Axis.vertical] and
  /// [controller] is null.
  final bool? primary;

  /// How the scroll view should respond to user input.
  ///
  /// For example, determines how the scroll view continues to animate after the
  /// user stops dragging the scroll view.
  ///
  /// Defaults to matching platform conventions.
  final ScrollPhysics? physics;

  /// Whether the extent of the scroll view in the [scrollDirection] should be
  /// determined by the contents being viewed.
  ///
  /// If the scroll view does not shrink wrap, then the scroll view will expand
  /// to the maximum allowed size in the [scrollDirection]. If the scroll view
  /// has unbounded constraints in the [scrollDirection], then [shrinkWrap] must
  /// be true.
  ///
  /// Shrink wrapping the content of the scroll view is significantly more
  /// expensive than expanding to the maximum allowed size because the content
  /// can expand and contract during scrolling, which means the size of the
  /// scroll view needs to be recomputed whenever the scroll position changes.
  ///
  /// Defaults to false.
  final bool shrinkWrap;

  /// The amount of space by which to inset the children.
  final EdgeInsetsGeometry? padding;

  /// The state from the closest instance of this class that encloses the given
  /// context.
  ///
  /// This method is typically used by [AnimatedList] item widgets that insert
  /// or remove items in response to user input.
  ///
  /// ```dart
  /// AnimatedListState animatedList = AnimatedList.of(context);
  /// ```
  static AnimatedListState? of(BuildContext context, { bool nullOk = false }) {
    assert(context != null);
    assert(nullOk != null);
    final AnimatedListState? result = context.findAncestorStateOfType<AnimatedListState>();
    if (nullOk || result != null)
      return result;
    throw FlutterError.fromParts(<DiagnosticsNode>[
      ErrorSummary('AnimatedList.of() called with a context that does not contain an AnimatedList.'),
      ErrorDescription('No AnimatedList ancestor could be found starting from the context that was passed to AnimatedList.of().'),
      ErrorHint(
        'This can happen when the context provided is from the same StatefulWidget that '
        'built the AnimatedList. Please see the AnimatedList documentation for examples '
        'of how to refer to an AnimatedListState object:'
        '  https://api.flutter.dev/flutter/widgets/AnimatedListState-class.html'
      ),
      context.describeElement('The context used was')
    ]);
  }

  @override
  AnimatedListState createState() => AnimatedListState();
}

/// The state for a scrolling container that animates items when they are
/// inserted or removed.
///
/// When an item is inserted with [insertItem] an animation begins running. The
/// animation is passed to [AnimatedList.itemBuilder] whenever the item's widget
/// is needed.
///
/// When an item is removed with [removeItem] its animation is reversed.
/// The removed item's animation is passed to the [removeItem] builder
/// parameter.
///
/// An app that needs to insert or remove items in response to an event
/// can refer to the [AnimatedList]'s state with a global key:
///
/// ```dart
/// GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
/// ...
/// AnimatedList(key: listKey, ...);
/// ...
/// listKey.currentState.insert(123);
/// ```
///
/// [AnimatedList] item input handlers can also refer to their [AnimatedListState]
/// with the static [AnimatedList.of] method.
class AnimatedListState extends State<AnimatedList> with TickerProviderStateMixin<AnimatedList> {
  final GlobalKey<SliverAnimatedListState> _sliverAnimatedListKey = GlobalKey();

  /// Insert an item at [index] and start an animation that will be passed
  /// to [AnimatedList.itemBuilder] when the item is visible.
  ///
  /// This method's semantics are the same as Dart's [List.insert] method:
  /// it increases the length of the list by one and shifts all items at or
  /// after [index] towards the end of the list.
  void insertItem(int index, { Duration duration = _kDuration }) {
    _sliverAnimatedListKey.currentState!.insertItem(index, duration: duration);
  }

  /// Remove the item at [index] and start an animation that will be passed
  /// to [builder] when the item is visible.
  ///
  /// Items are removed immediately. After an item has been removed, its index
  /// will no longer be passed to the [AnimatedList.itemBuilder]. However the
  /// item will still appear in the list for [duration] and during that time
  /// [builder] must construct its widget as needed.
  ///
  /// This method's semantics are the same as Dart's [List.remove] method:
  /// it decreases the length of the list by one and shifts all items at or
  /// before [index] towards the beginning of the list.
  void removeItem(int index, AnimatedListRemovedItemBuilder builder, { Duration duration = _kDuration }) {
    _sliverAnimatedListKey.currentState!.removeItem(index, builder, duration: duration);
  }

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      scrollDirection: widget.scrollDirection,
      reverse: widget.reverse,
      controller: widget.controller,
      primary: widget.primary,
      physics: widget.physics,
      shrinkWrap: widget.shrinkWrap,
      slivers: <Widget>[
        SliverPadding(
          padding: widget.padding ?? const EdgeInsets.all(0),
          sliver: SliverAnimatedList(
            key: _sliverAnimatedListKey,
            itemBuilder: widget.itemBuilder,
            initialItemCount: widget.initialItemCount,
          ),
        ),
      ],
    );
  }
}

/// A sliver that animates items when they are inserted or removed.
///
/// This widget's [SliverAnimatedListState] can be used to dynamically insert or
/// remove items. To refer to the [SliverAnimatedListState] either provide a
/// [GlobalKey] or use the static [SliverAnimatedList.of] method from an item's
/// input callback.
///
/// {@tool dartpad --template=freeform}
/// This sample application uses a [SliverAnimatedList] to create an animated
/// effect when items are removed or added to the list.
///
/// ```dart imports
/// import 'package:flutter/foundation.dart';
/// import 'package:flutter/material.dart';
/// ```
///
/// ```dart
/// void main() => runApp(SliverAnimatedListSample());
///
/// class SliverAnimatedListSample extends StatefulWidget {
///   @override
///   _SliverAnimatedListSampleState createState() => _SliverAnimatedListSampleState();
/// }
///
/// class _SliverAnimatedListSampleState extends State<SliverAnimatedListSample> {
///   final GlobalKey<SliverAnimatedListState> _listKey = GlobalKey<SliverAnimatedListState>();
///   final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
///   final GlobalKey<ScaffoldMessengerState> _scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
///   ListModel<int> _list;
///   int _selectedItem;
///   int _nextItem; // The next item inserted when the user presses the '+' button.
///
///   @override
///   void initState() {
///     super.initState();
///     _list = ListModel<int>(
///       listKey: _listKey,
///       initialItems: <int>[0, 1, 2],
///       removedItemBuilder: _buildRemovedItem,
///     );
///     _nextItem = 3;
///   }
///
///   // Used to build list items that haven't been removed.
///   Widget _buildItem(BuildContext context, int index, Animation<double> animation) {
///     return CardItem(
///       animation: animation,
///       item: _list[index],
///       selected: _selectedItem == _list[index],
///       onTap: () {
///         setState(() {
///           _selectedItem = _selectedItem == _list[index] ? null : _list[index];
///         });
///       },
///     );
///   }
///
///   // Used to build an item after it has been removed from the list. This
///   // method is needed because a removed item remains visible until its
///   // animation has completed (even though it's gone as far this ListModel is
///   // concerned). The widget will be used by the
///   // [AnimatedListState.removeItem] method's
///   // [AnimatedListRemovedItemBuilder] parameter.
///   Widget _buildRemovedItem(int item, BuildContext context, Animation<double> animation) {
///     return CardItem(
///       animation: animation,
///       item: item,
///       selected: false,
///     );
///   }
///
///   // Insert the "next item" into the list model.
///   void _insert() {
///     final int index = _selectedItem == null ? _list.length : _list.indexOf(_selectedItem);
///     _list.insert(index, _nextItem++);
///   }
///
///   // Remove the selected item from the list model.
///   void _remove() {
///     if (_selectedItem != null) {
///       _list.removeAt(_list.indexOf(_selectedItem));
///       setState(() {
///         _selectedItem = null;
///       });
///     } else {
///       _scaffoldMessengerKey.currentState.showSnackBar(SnackBar(
///         content: Text(
///           'Select an item to remove from the list.',
///           style: TextStyle(fontSize: 20),
///         ),
///       ));
///     }
///   }
///
///   @override
///   Widget build(BuildContext context) {
///     return MaterialApp(
///       scaffoldMessengerKey: _scaffoldMessengerKey,
///       home: Scaffold(
///         key: _scaffoldKey,
///         body: CustomScrollView(
///           slivers: <Widget>[
///             SliverAppBar(
///               title: Text(
///                 'SliverAnimatedList',
///                 style: TextStyle(fontSize: 30),
///               ),
///               expandedHeight: 60,
///               centerTitle: true,
///               backgroundColor: Colors.amber[900],
///               leading: IconButton(
///                 icon: const Icon(Icons.add_circle),
///                 onPressed: _insert,
///                 tooltip: 'Insert a new item.',
///                 iconSize: 32,
///               ),
///               actions: [
///                 IconButton(
///                   icon: const Icon(Icons.remove_circle),
///                   onPressed: _remove,
///                   tooltip: 'Remove the selected item.',
///                   iconSize: 32,
///                 ),
///               ],
///             ),
///             SliverAnimatedList(
///               key: _listKey,
///               initialItemCount: _list.length,
///               itemBuilder: _buildItem,
///             ),
///           ],
///         ),
///       ),
///     );
///   }
/// }
///
/// // Keeps a Dart [List] in sync with an [AnimatedList].
/// //
/// // The [insert] and [removeAt] methods apply to both the internal list and
/// // the animated list that belongs to [listKey].
/// //
/// // This class only exposes as much of the Dart List API as is needed by the
/// // sample app. More list methods are easily added, however methods that
/// // mutate the list must make the same changes to the animated list in terms
/// // of [AnimatedListState.insertItem] and [AnimatedList.removeItem].
/// class ListModel<E> {
///   ListModel({
///     @required this.listKey,
///     @required this.removedItemBuilder,
///     Iterable<E> initialItems,
///   }) : assert(listKey != null),
///        assert(removedItemBuilder != null),
///        _items = List<E>.from(initialItems ?? <E>[]);
///
///   final GlobalKey<SliverAnimatedListState> listKey;
///   final dynamic removedItemBuilder;
///   final List<E> _items;
///
///   SliverAnimatedListState get _animatedList => listKey.currentState;
///
///   void insert(int index, E item) {
///     _items.insert(index, item);
///     _animatedList.insertItem(index);
///   }
///
///   E removeAt(int index) {
///     final E removedItem = _items.removeAt(index);
///     if (removedItem != null) {
///       _animatedList.removeItem(
///         index,
///         (BuildContext context, Animation<double> animation) => removedItemBuilder(removedItem, context, animation),
///       );
///     }
///     return removedItem;
///   }
///
///   int get length => _items.length;
///
///   E operator [](int index) => _items[index];
///
///   int indexOf(E item) => _items.indexOf(item);
/// }
///
/// // Displays its integer item as 'Item N' on a Card whose color is based on
/// // the item's value.
/// //
/// // The card turns gray when [selected] is true. This widget's height
/// // is based on the [animation] parameter. It varies as the animation value
/// // transitions from 0.0 to 1.0.
/// class CardItem extends StatelessWidget {
///   const CardItem({
///     Key key,
///     @required this.animation,
///     @required this.item,
///     this.onTap,
///     this.selected = false,
///   }) : assert(animation != null),
///        assert(item != null && item >= 0),
///        assert(selected != null),
///        super(key: key);
///
///   final Animation<double> animation;
///   final VoidCallback onTap;
///   final int item;
///   final bool selected;
///
///   @override
///   Widget build(BuildContext context) {
///     return Padding(
///       padding:
///       const EdgeInsets.only(
///         left: 2.0,
///         right: 2.0,
///         top: 2.0,
///         bottom: 0.0,
///       ),
///       child: SizeTransition(
///         axis: Axis.vertical,
///         sizeFactor: animation,
///         child: GestureDetector(
///           onTap: onTap,
///           child: SizedBox(
///             height: 80.0,
///             child: Card(
///               color: selected
///                 ? Colors.black12
///                 : Colors.primaries[item % Colors.primaries.length],
///               child: Center(
///                 child: Text(
///                   'Item $item',
///                   style: Theme.of(context).textTheme.headline4,
///                 ),
///               ),
///             ),
///           ),
///         ),
///       ),
///     );
///   }
/// }
/// ```
/// {@end-tool}
///
/// See also:
///
///  * [SliverList], which does not animate items when they are inserted or
///    removed.
///  * [AnimatedList], a non-sliver scrolling container that animates items when
///    they are inserted or removed.
class SliverAnimatedList extends StatefulWidget {
  /// Creates a sliver that animates items when they are inserted or removed.
  const SliverAnimatedList({
    Key? key,
    required this.itemBuilder,
    this.initialItemCount = 0,
  }) : assert(itemBuilder != null),
       assert(initialItemCount != null && initialItemCount >= 0),
       super(key: key);

  /// Called, as needed, to build list item widgets.
  ///
  /// List items are only built when they're scrolled into view.
  ///
  /// The [AnimatedListItemBuilder] index parameter indicates the item's
  /// position in the list. The value of the index parameter will be between 0
  /// and [initialItemCount] plus the total number of items that have been
  /// inserted with [SliverAnimatedListState.insertItem] and less the total
  /// number of items that have been removed with
  /// [SliverAnimatedListState.removeItem].
  ///
  /// Implementations of this callback should assume that
  /// [SliverAnimatedListState.removeItem] removes an item immediately.
  final AnimatedListItemBuilder itemBuilder;

  /// {@macro flutter.widgets.animatedList.initialItemCount}
  final int initialItemCount;

  @override
  SliverAnimatedListState createState() => SliverAnimatedListState();

  /// The state from the closest instance of this class that encloses the given
  /// context.
  ///
  /// This method is typically used by [SliverAnimatedList] item widgets that
  /// insert or remove items in response to user input.
  ///
  /// ```dart
  /// SliverAnimatedListState animatedList = SliverAnimatedList.of(context);
  /// ```
  static SliverAnimatedListState? of(BuildContext context, {bool nullOk = false}) {
    assert(context != null);
    assert(nullOk != null);
    final SliverAnimatedListState? result = context.findAncestorStateOfType<SliverAnimatedListState>();
    if (nullOk || result != null)
      return result;
    throw FlutterError(
        'SliverAnimatedList.of() called with a context that does not contain a SliverAnimatedList.\n'
        'No SliverAnimatedListState ancestor could be found starting from the '
        'context that was passed to SliverAnimatedListState.of(). This can '
        'happen when the context provided is from the same StatefulWidget that '
        'built the AnimatedList. Please see the SliverAnimatedList documentation '
        'for examples of how to refer to an AnimatedListState object: '
        'https://docs.flutter.io/flutter/widgets/SliverAnimatedListState-class.html \n'
        'The context used was:\n'
        '  $context');
  }
}

/// The state for a sliver that animates items when they are
/// inserted or removed.
///
/// When an item is inserted with [insertItem] an animation begins running. The
/// animation is passed to [SliverAnimatedList.itemBuilder] whenever the item's
/// widget is needed.
///
/// When an item is removed with [removeItem] its animation is reversed.
/// The removed item's animation is passed to the [removeItem] builder
/// parameter.
///
/// An app that needs to insert or remove items in response to an event
/// can refer to the [SliverAnimatedList]'s state with a global key:
///
/// ```dart
/// GlobalKey<SliverAnimatedListState> listKey = GlobalKey<SliverAnimatedListState>();
/// ...
/// SliverAnimatedList(key: listKey, ...);
/// ...
/// listKey.currentState.insert(123);
/// ```
///
/// [SliverAnimatedList] item input handlers can also refer to their
/// [SliverAnimatedListState] with the static [SliverAnimatedList.of] method.
class SliverAnimatedListState extends State<SliverAnimatedList> with TickerProviderStateMixin {

  final List<_ActiveItem> _incomingItems = <_ActiveItem>[];
  final List<_ActiveItem> _outgoingItems = <_ActiveItem>[];
  int _itemsCount = 0;

  @override
  void initState() {
    super.initState();
    _itemsCount = widget.initialItemCount;
  }

  @override
  void dispose() {
    for (final _ActiveItem item in _incomingItems.followedBy(_outgoingItems)) {
      item.controller!.dispose();
    }
    super.dispose();
  }

  _ActiveItem? _removeActiveItemAt(List<_ActiveItem> items, int itemIndex) {
    final int i = binarySearch(items, _ActiveItem.index(itemIndex));
    return i == -1 ? null : items.removeAt(i);
  }

  _ActiveItem? _activeItemAt(List<_ActiveItem> items, int itemIndex) {
    final int i = binarySearch(items, _ActiveItem.index(itemIndex));
    return i == -1 ? null : items[i];
  }

  // The insertItem() and removeItem() index parameters are defined as if the
  // removeItem() operation removed the corresponding list entry immediately.
  // The entry is only actually removed from the ListView when the remove animation
  // finishes. The entry is added to _outgoingItems when removeItem is called
  // and removed from _outgoingItems when the remove animation finishes.

  int _indexToItemIndex(int index) {
    int itemIndex = index;
    for (final _ActiveItem item in _outgoingItems) {
      if (item.itemIndex <= itemIndex)
        itemIndex += 1;
      else
        break;
    }
    return itemIndex;
  }

  int _itemIndexToIndex(int itemIndex) {
    int index = itemIndex;
    for (final _ActiveItem item in _outgoingItems) {
      assert(item.itemIndex != itemIndex);
      if (item.itemIndex < itemIndex)
        index -= 1;
      else
        break;
    }
    return index;
  }

  SliverChildDelegate _createDelegate() {
    return SliverChildBuilderDelegate(_itemBuilder, childCount: _itemsCount);
  }

  /// Insert an item at [index] and start an animation that will be passed to
  /// [SliverAnimatedList.itemBuilder] when the item is visible.
  ///
  /// This method's semantics are the same as Dart's [List.insert] method:
  /// it increases the length of the list by one and shifts all items at or
  /// after [index] towards the end of the list.
  void insertItem(int index, { Duration duration = _kDuration }) {
    assert(index != null && index >= 0);
    assert(duration != null);

    final int itemIndex = _indexToItemIndex(index);
    assert(itemIndex >= 0 && itemIndex <= _itemsCount);

    // Increment the incoming and outgoing item indices to account
    // for the insertion.
    for (final _ActiveItem item in _incomingItems) {
      if (item.itemIndex >= itemIndex)
        item.itemIndex += 1;
    }
    for (final _ActiveItem item in _outgoingItems) {
      if (item.itemIndex >= itemIndex)
        item.itemIndex += 1;
    }

    final AnimationController controller = AnimationController(
      duration: duration,
      vsync: this,
    );
    final _ActiveItem incomingItem = _ActiveItem.incoming(
      controller,
      itemIndex,
    );
    setState(() {
      _incomingItems
        ..add(incomingItem)
        ..sort();
      _itemsCount += 1;
    });

    controller.forward().then<void>((_) {
      _removeActiveItemAt(_incomingItems, incomingItem.itemIndex)!.controller!.dispose();
    });
  }

  /// Remove the item at [index] and start an animation that will be passed
  /// to [builder] when the item is visible.
  ///
  /// Items are removed immediately. After an item has been removed, its index
  /// will no longer be passed to the [SliverAnimatedList.itemBuilder]. However
  /// the item will still appear in the list for [duration] and during that time
  /// [builder] must construct its widget as needed.
  ///
  /// This method's semantics are the same as Dart's [List.remove] method:
  /// it decreases the length of the list by one and shifts all items at or
  /// before [index] towards the beginning of the list.
  void removeItem(int index, AnimatedListRemovedItemBuilder builder, { Duration duration = _kDuration }) {
    assert(index != null && index >= 0);
    assert(builder != null);
    assert(duration != null);

    final int itemIndex = _indexToItemIndex(index);
    assert(itemIndex >= 0 && itemIndex < _itemsCount);
    assert(_activeItemAt(_outgoingItems, itemIndex) == null);

    final _ActiveItem? incomingItem = _removeActiveItemAt(_incomingItems, itemIndex);
    final AnimationController controller = incomingItem?.controller
      ?? AnimationController(duration: duration, value: 1.0, vsync: this);
    final _ActiveItem outgoingItem = _ActiveItem.outgoing(controller, itemIndex, builder);
    setState(() {
      _outgoingItems
        ..add(outgoingItem)
        ..sort();
    });

    controller.reverse().then<void>((void value) {
      _removeActiveItemAt(_outgoingItems, outgoingItem.itemIndex)!.controller!.dispose();

      // Decrement the incoming and outgoing item indices to account
      // for the removal.
      for (final _ActiveItem item in _incomingItems) {
        if (item.itemIndex > outgoingItem.itemIndex)
          item.itemIndex -= 1;
      }
      for (final _ActiveItem item in _outgoingItems) {
        if (item.itemIndex > outgoingItem.itemIndex)
          item.itemIndex -= 1;
      }

      setState(() => _itemsCount -= 1);
    });
  }

  Widget _itemBuilder(BuildContext context, int itemIndex) {
    final _ActiveItem? outgoingItem = _activeItemAt(_outgoingItems, itemIndex);
    if (outgoingItem != null) {
      return outgoingItem.removedItemBuilder!(
        context,
        outgoingItem.controller!.view,
      );
    }

    final _ActiveItem? incomingItem = _activeItemAt(_incomingItems, itemIndex);
    final Animation<double> animation = incomingItem?.controller?.view ?? kAlwaysCompleteAnimation;
    return widget.itemBuilder(
      context,
      _itemIndexToIndex(itemIndex),
      animation,
    );
  }

  @override
  Widget build(BuildContext context) {
    return SliverList(
      delegate: _createDelegate(),
    );
  }
}
