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

/// @docImport 'color_scheme.dart';
library;

import 'dart:math' as math;

import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';

import 'carousel_theme.dart';
import 'color_scheme.dart';
import 'colors.dart';
import 'ink_well.dart';
import 'material.dart';
import 'theme.dart';

// Examples can assume:
// late BuildContext context;

/// A Material Design carousel widget.
///
/// The [CarouselView] presents a scrollable list of items, each of which can dynamically
/// change size based on the chosen layout.
///
/// Material Design 3 introduced 4 carousel layouts:
///  * Multi-browse: This layout shows at least one large, medium, and small
///    carousel item at a time. This layout is supported by [CarouselView.weighted].
///  * Uncontained (default): This layout show items that scroll to the edge of the
///    container. This layout is supported by [CarouselView].
///  * Hero: This layout shows at least one large and one small item at a time.
///    This layout is supported by [CarouselView.weighted].
///  * Full-screen: This layout shows one edge-to-edge large item at a time and
///    scrolls vertically. The full-screen layout can be supported by both
///    constructors.
///
/// The default constructor implements the uncontained layout model. It shows
/// items that scroll to the edge of the container, behaving similarly to a
/// [ListView] where all children are a uniform size. [CarouselView.weighted]
/// enables dynamic item sizing. Each item is assigned a weight that determines
/// the portion of the viewport it occupies. This constructor helps to create
/// layouts like multi-browse, and hero. In order to have a full-screen layout,
/// if [CarouselView] is used, then set the [itemExtent] to screen size; if
/// [CarouselView.weighted] is used, then set the [flexWeights] to only have
/// one integer in the array.
///
/// {@tool snippet}
///
/// This code snippet shows how to get a vertical full-screen carousel by using
/// [itemExtent] in [CarouselView].
///
/// ```dart
/// Scaffold(
///   body: CarouselView(
///     scrollDirection: Axis.vertical,
///     itemExtent: double.infinity,
///     children: List<Widget>.generate(10, (int index) {
///       return Center(child: Text('Item $index'));
///     }),
///   ),
/// ),
/// ```
///
/// This code snippet below shows how to achieve the same vertical full-screen
/// carousel by using [flexWeights] in [CarouselView.weighted].
///
/// ```dart
/// Scaffold(
///   body: CarouselView.weighted(
///     scrollDirection: Axis.vertical,
///     flexWeights: const <int>[1], // Or any positive integers as long as the length of the array is 1.
///     children: List<Widget>.generate(10, (int index) {
///       return Center(child: Text('Item $index'));
///     }),
///   ),
/// ),
/// ```
/// {@end-tool}
///
/// In [CarouselView.weighted], weights are relative proportions. For example,
/// if the layout weights is `[3, 2, 1]`, it means the first visible item occupies
/// 3/6 of the viewport; the second visible item occupies 2/6 of the viewport;
/// the last visible item occupies 1/6 of the viewport. As the carousel scrolls,
/// the size of the latter one gradually changes to the size of the former one.
/// As a result, when the first visible item is completely off-screen, the
/// following items will follow the same layout as before. Using [CarouselView.weighted]
/// helps build the multi-browse, hero, center-aligned hero and full-screen layouts,
/// as indicated in [Carousel specs](https://m3.material.io/components/carousel/specs).
///
/// The [CarouselController] is used to control the
/// [CarouselController.initialItem], which determines the first fully expanded
/// item when the [CarouselView] or [CarouselView.weighted] is initially displayed.
/// This is straightforward for [CarouselView] because each item in the view
/// has fixed size. In [CarouselView.weighted], for instance, if the layout
/// weights are `[1, 2, 3, 2, 1]` and the initial item is 4 (the fourth item), the
/// view will display items 2, 3, 4, 5, and 6 with weights 1, 2, 3, 2 and 1
/// respectively.
///
/// The [CarouselView.itemExtent] property must be non-null and defines the base
/// size of items. While items typically maintain this size, the first and last
/// visible items may be slightly compressed during scrolling. The [shrinkExtent]
/// property controls the minimum allowable size for these compressed items.
///
/// {@tool dartpad}
/// Here is an example to show different carousel layouts that [CarouselView]
/// and [CarouselView.weighted] can build.
///
/// On desktop and web running on desktop platforms, dragging to scroll with a mouse
/// is disabled by default to align with natural behavior.
///
/// To further align expected behavior like this, mouse input can scroll horizontally
/// by pressing the shift key while scrolling with the mouse wheel.
///
/// This key-driven behavior is dictated by the [ScrollBehavior.pointerAxisModifiers],
/// while [ScrollBehavior.dragDevices] manages what devices can drag a scrollable.
///
/// ** See code in examples/api/lib/material/carousel/carousel.0.dart **
/// {@end-tool}
///
/// See also:
///
///  * [CarouselController], which controls the first fully visible item in the
///    view.
///  * [PageView], which is a scrollable list that works page by page.
class CarouselView extends StatefulWidget {
  /// Creates a Material Design carousel.
  const CarouselView({
    super.key,
    this.padding,
    this.backgroundColor,
    this.elevation,
    this.shape,
    this.itemClipBehavior,
    this.overlayColor,
    this.itemSnapping = false,
    this.shrinkExtent = 0.0,
    this.controller,
    this.scrollDirection = Axis.horizontal,
    this.reverse = false,
    this.onTap,
    this.enableSplash = true,
    required double this.itemExtent,
    required this.children,
    this.onIndexChanged,
  }) : consumeMaxWeight = true,
       flexWeights = null,
       itemBuilder = null,
       itemCount = null;

  /// Creates a scrollable list where the size of each child widget is dynamically
  /// determined by the provided [flexWeights].
  ///
  /// The [flexWeights] parameter is required and defines the relative size
  /// proportions of each child widget.
  ///
  /// While scrolling, the main-axis extent (size) of each visible item changes
  /// dynamically based on the scrolling progress. The cross-axis extent is determined
  /// by the parent constraints. As the first visible item scrolls completely
  /// off-screen, the next item becomes the first visible item, and has the same
  /// size as the previously first item. The rest of the visible items maintain
  /// their relative layout.
  ///
  /// For example, if the layout weights are `[1, 6, 1]`, the length of [flexWeights]
  /// indicates three items will be visible at a time. The layout of these items
  /// would be:
  ///  * First item: Extent is (1 / (1 + 6 + 1)) * viewport extent.
  ///  * Second item: Extent is (6 / (1 + 6 + 1)) * viewport extent.
  ///  * Third item: Extent is (1 / (1 + 6 + 1)) * viewport extent.
  ///
  /// Assuming a viewport extent of 800 in the main axis and the first item is
  /// item 0, there would be three visible items with extents of 100, 600, and 100.
  /// As item 0 scrolls off-screen, the extent of item 1 smoothly decreases from 600
  /// to 100. For instance, if item 0 is 30% off-screen, item 1 should have decreased
  /// its size to 30% of the difference from 600 to 100; its extent would be
  /// 600 - 0.3 * (600 - 100). Similarly, item 2's extent would increase from 100
  /// to 600, becoming 100 + 0.3 * (600 - 100).
  ///
  /// As the initially visible items change size during scrolling, item 3 enters
  /// the view to fill the remaining space. Its extent starts at a minimum of
  /// [shrinkExtent] (or 0 if [shrinkExtent] is not provided) and gradually
  /// increases to match the extent of the last visible item (100 in this example).
  ///
  /// When [consumeMaxWeight] is set to `true`, each child can be expanded to occupy
  /// the maximum weight while scrolling. For example, with [flexWeights] of `[1, 7, 1]`,
  /// the initial weight of the first item is 1. However, by enabling
  /// [consumeMaxWeight] and scrolling forward, the first item can expand to occupy
  /// a weight of 7, leaving a weight of 1 as some empty space before it. This feature
  /// is particularly useful for achieving [Hero](https://m3.material.io/components/carousel/specs#b33a5579-d648-42a9-b934-98718d65454f)
  /// and [Center-aligned hero](https://m3.material.io/components/carousel/specs#92c779ce-de8b-4dee-8201-95d3e429204f)
  /// layouts indicated in the Material Design 3.
  const CarouselView.weighted({
    super.key,
    this.padding,
    this.backgroundColor,
    this.elevation,
    this.shape,
    this.itemClipBehavior,
    this.overlayColor,
    this.itemSnapping = false,
    this.shrinkExtent = 0.0,
    this.controller,
    this.scrollDirection = Axis.horizontal,
    this.reverse = false,
    this.consumeMaxWeight = true,
    this.onTap,
    this.enableSplash = true,
    required List<int> this.flexWeights,
    required this.children,
    this.onIndexChanged,
  }) : itemExtent = null,
       itemBuilder = null,
       itemCount = null;

  /// Creates a scrollable carousel with fixed-sized items created on demand.
  ///
  /// This constructor allows lazy loading of carousel items. Only items that
  /// are visible (or about to be visible) are built, improving performance
  /// when dealing with large numbers of items.
  ///
  /// The [itemBuilder] callback will be called only with indices greater than
  /// or equal to zero and less than [itemCount].
  ///
  /// {@tool dartpad}
  /// This example shows how to create a carousel with 1000 items using lazy loading:
  ///
  /// ** See code in examples/api/lib/material/carousel/carousel.1.dart **
  /// {@end-tool}
  ///
  /// See also:
  ///
  ///  * [CarouselView.new], which creates a carousel with explicit children.
  ///  * [CarouselView.weighted], which creates a carousel with weighted items.
  ///  * [CarouselView.weightedBuilder], which creates a carousel with weighted
  ///    items using lazy loading.
  const CarouselView.builder({
    super.key,
    this.padding,
    this.backgroundColor,
    this.elevation,
    this.shape,
    this.itemClipBehavior,
    this.overlayColor,
    this.itemSnapping = false,
    this.shrinkExtent = 0.0,
    this.controller,
    this.scrollDirection = Axis.horizontal,
    this.reverse = false,
    this.onTap,
    this.enableSplash = true,
    required double this.itemExtent,
    required this.itemBuilder,
    this.itemCount,
    this.onIndexChanged,
  }) : consumeMaxWeight = true,
       flexWeights = null,
       children = const <Widget>[];

  /// Creates a scrollable carousel with weighted items created on demand.
  ///
  /// This constructor combines the benefits of [CarouselView.weighted] with
  /// lazy loading. Items are built on demand while maintaining the weighted
  /// layout system.
  ///
  /// The [flexWeights] parameter determines the layout, and [itemBuilder]
  /// creates items as they become visible.
  ///
  /// {@tool snippet}
  /// This example shows how to create a weighted carousel with lazy loading:
  ///
  /// ```dart
  /// CarouselView.weightedBuilder(
  ///   flexWeights: const <int>[1, 7, 1],
  ///   itemCount: 100,
  ///   itemBuilder: (BuildContext context, int index) {
  ///     return ColoredBox(
  ///       color: Colors.primaries[index % Colors.primaries.length],
  ///       child: Center(
  ///         child: Text('Item $index'),
  ///       ),
  ///     );
  ///   },
  /// )
  /// ```
  /// {@end-tool}
  ///
  /// See also:
  ///
  ///  * [CarouselView.new], which creates a carousel with explicit children.
  ///  * [CarouselView.weighted], which creates a carousel with weighted items.
  ///  * [CarouselView.builder], which creates a carousel with fixed-sized items
  ///    using lazy loading.
  const CarouselView.weightedBuilder({
    super.key,
    this.padding,
    this.backgroundColor,
    this.elevation,
    this.shape,
    this.itemClipBehavior,
    this.overlayColor,
    this.itemSnapping = false,
    this.shrinkExtent = 0.0,
    this.controller,
    this.scrollDirection = Axis.horizontal,
    this.reverse = false,
    this.consumeMaxWeight = true,
    this.onTap,
    this.enableSplash = true,
    required List<int> this.flexWeights,
    required this.itemBuilder,
    this.itemCount,
    this.onIndexChanged,
  }) : itemExtent = null,
       children = const <Widget>[];

  /// The amount of space to surround each carousel item with.
  ///
  /// Defaults to [EdgeInsets.all] of 4 pixels.
  final EdgeInsets? padding;

  /// The background color for each carousel item.
  ///
  /// Defaults to [ColorScheme.surface].
  final Color? backgroundColor;

  /// The z-coordinate of each carousel item.
  ///
  /// Defaults to 0.0.
  final double? elevation;

  /// The shape of each carousel item's [Material].
  ///
  /// Defines each item's [Material.shape].
  ///
  /// Defaults to a [RoundedRectangleBorder] with a circular corner radius
  /// of 28.0.
  final ShapeBorder? shape;

  /// The clip behavior for each carousel item.
  ///
  /// The item content will be clipped (or not) according to this option.
  /// Refer to the [Clip] enum for more details on the different clip options.
  ///
  /// Defaults to [Clip.antiAlias].
  final Clip? itemClipBehavior;

  /// The highlight color to indicate the carousel items are in pressed, hovered
  /// or focused states.
  ///
  /// The default values are:
  ///   * [WidgetState.pressed] - [ColorScheme.onSurface] with an opacity of 0.1
  ///   * [WidgetState.hovered] - [ColorScheme.onSurface] with an opacity of 0.08
  ///   * [WidgetState.focused] - [ColorScheme.onSurface] with an opacity of 0.1
  final WidgetStateProperty<Color?>? overlayColor;

  /// The minimum allowable extent (size) in the main axis for carousel items
  /// during scrolling transitions.
  ///
  /// As the carousel scrolls, the first visible item is pinned and gradually
  /// shrinks until it reaches this minimum extent before scrolling off-screen.
  /// Similarly, the last visible item enters the viewport at this minimum size
  /// and expands to its full [itemExtent].
  ///
  /// In cases where the remaining viewport space for the last visible item is
  /// larger than the defined [shrinkExtent], the [shrinkExtent] is dynamically
  /// adjusted to match this remaining space, ensuring a smooth size transition.
  ///
  /// Defaults to 0.0. Setting to 0.0 allows items to shrink/expand completely,
  /// transitioning between 0.0 and the full item size. In cases where the
  /// remaining viewport space for the last visible item is larger than the
  /// defined [shrinkExtent], the [shrinkExtent] is dynamically adjusted to match
  /// this remaining space, ensuring a smooth size transition.
  final double shrinkExtent;

  /// Whether the carousel should keep scrolling to the next/previous items to
  /// maintain the original layout.
  ///
  /// Defaults to false.
  final bool itemSnapping;

  /// An object that can be used to control the position to which this scroll
  /// view is scrolled.
  final CarouselController? controller;

  /// The [Axis] along which the scroll view's offset increases with each item.
  ///
  /// Defaults to [Axis.horizontal].
  final Axis scrollDirection;

  /// Whether the carousel list scrolls in the reading direction.
  ///
  /// For example, if the reading direction is left-to-right and
  /// [scrollDirection] is [Axis.horizontal], then the carousel 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 carousel 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;

  /// Whether the collapsed items are allowed to expand to the max size.
  ///
  /// If this is false, the layout of the carousel doesn't change. This is especially
  /// useful when a weight list in [CarouselView.weighted] has a max item in the
  /// middle and at least one small item on either side, such as `[1, 7, 1, 1]`.
  /// In this case, if this is false, the first and the last two items cannot
  /// expand to the max size. If this is true, there will be some space before
  /// the first item or after the last item coming so every item has a chance to
  /// be fully expanded.
  ///
  /// Defaults to true.
  final bool consumeMaxWeight;

  /// Called when one of the [children] is tapped.
  final ValueChanged<int>? onTap;

  /// Determines whether an [InkWell] will cover each Carousel item.
  ///
  /// If true, tapping an item will create an ink splash
  /// as defined by the [ThemeData.splashFactory].
  ///
  /// Setting this to false allows the [children] to respond to user gestures.
  ///
  /// Defaults to true.
  final bool enableSplash;

  /// The extent the children are forced to have in the main axis.
  ///
  /// The item extent should not exceed the available space that the carousel view
  /// occupies to ensure at least one item is fully visible.
  ///
  /// This is required for [CarouselView]. In [CarouselView.weighted], this is null.
  final double? itemExtent;

  /// The weights that each visible child should occupy in the viewport.
  ///
  /// The length of [flexWeights] represents how many items should be visible
  /// at a time in the viewport. For example, setting [flexWeights] to
  /// `<int>[3, 2, 1]` means there are 3 carousel items and their extents are
  /// 3/6, 2/6 and 1/6 of the viewport extent.
  ///
  /// This is a required property in [CarouselView.weighted]. This is null
  /// for default [CarouselView]. The integers must be greater than 0.
  final List<int>? flexWeights;

  /// The child widgets for the carousel.
  final List<Widget> children;

  /// {@template flutter.material.CarouselView.onIndexChanged}
  /// A callback invoked when the leading item changes.
  ///
  /// The leading item is the first visible item in the carousel view.
  ///
  /// The callback fires only when the leading item is completely out of view,
  /// whether due to user interaction or programmatic scrolling. If the leading item
  /// remains partially visible, the leading index will not change and the callback will
  /// not be invoked.
  /// {@endtemplate}
  ///
  /// Example:
  ///
  /// ```dart
  /// CarouselView(
  ///   itemExtent: 200.0,
  ///   onIndexChanged: (int index) {
  ///     print('Leading item changed to: $index');
  ///   },
  ///   children: <Widget>[
  ///     Container(color: Colors.red),
  ///     Container(color: Colors.green),
  ///     Container(color: Colors.blue),
  ///   ],
  /// )
  /// ```
  final ValueChanged<int>? onIndexChanged;

  /// Called to build carousel item on demand.
  ///
  /// Will be called only for indices greater than or equal to zero and less
  /// than [itemCount] (if [itemCount] is non-null).
  ///
  /// Should return null if asked to build a widget with a greater index than
  /// exists.
  final NullableIndexedWidgetBuilder? itemBuilder;

  /// The number of items in the carousel.
  ///
  /// If null, the carousel will continue to build items until [itemBuilder] returns null.
  final int? itemCount;

  @override
  State<CarouselView> createState() => _CarouselViewState();
}

class _CarouselViewState extends State<CarouselView> {
  double? _itemExtent;
  List<int>? get _flexWeights => widget.flexWeights;
  bool get _consumeMaxWeight => widget.consumeMaxWeight;
  CarouselController? _internalController;
  CarouselController get _controller => widget.controller ?? _internalController!;
  late int _lastReportedLeadingItem;

  @override
  void initState() {
    super.initState();
    _itemExtent = widget.itemExtent;
    if (widget.controller == null) {
      _internalController = CarouselController();
    }
    _lastReportedLeadingItem = _getInitialLeadingItem();
    _controller._attach(this);
    _controller.addListener(_handleScroll);
  }

  @override
  void didUpdateWidget(covariant CarouselView oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.controller != oldWidget.controller) {
      oldWidget.controller?._detach(this);
      if (widget.controller != null) {
        _internalController?._detach(this);
        _internalController = null;
        widget.controller?._attach(this);
      } else {
        // widget.controller == null && oldWidget.controller != null
        assert(_internalController == null);
        _internalController = CarouselController();
        _controller._attach(this);
      }
    }
    if (widget.flexWeights != oldWidget.flexWeights) {
      (_controller.position as _CarouselPosition).flexWeights = _flexWeights;
    }
    if (widget.itemExtent != oldWidget.itemExtent) {
      _itemExtent = widget.itemExtent;
      (_controller.position as _CarouselPosition).itemExtent = _itemExtent;
    }
    if (widget.consumeMaxWeight != oldWidget.consumeMaxWeight) {
      (_controller.position as _CarouselPosition).consumeMaxWeight = _consumeMaxWeight;
    }
  }

  @override
  void dispose() {
    _controller.removeListener(_handleScroll);
    _controller._detach(this);
    _internalController?.dispose();
    super.dispose();
  }

  void _handleScroll() {
    if (widget.onIndexChanged == null) {
      return;
    }

    final ScrollPosition position = _controller.position;
    final int currentLeadingIndex = (position as _CarouselPosition).leadingItem;

    if (currentLeadingIndex != _lastReportedLeadingItem) {
      _lastReportedLeadingItem = currentLeadingIndex;
      widget.onIndexChanged!(currentLeadingIndex);
    }
  }

  // For weighted carousel, the initialItem means the index of the item to occupy the first maximum weight
  // in flexWeights. To get the initial leading item, it should be initialItem - index of the first max weight in flexWeights.
  // So it might be negative when initialItem value is small but the first max weight index is large. In that case,
  // the initial leading item should be 0.
  int _getInitialLeadingItem() {
    if (widget.flexWeights != null) {
      final int maxWeight = widget.flexWeights!.max;
      final int firstMaxWeightIndex = widget.flexWeights!.indexOf(maxWeight);
      return math.max(_controller.initialItem - firstMaxWeightIndex, 0);
    }
    return _controller.initialItem;
  }

  AxisDirection _getDirection(BuildContext context) {
    switch (widget.scrollDirection) {
      case Axis.horizontal:
        assert(debugCheckHasDirectionality(context));
        final TextDirection textDirection = Directionality.of(context);
        final AxisDirection axisDirection = textDirectionToAxisDirection(textDirection);
        return widget.reverse ? flipAxisDirection(axisDirection) : axisDirection;
      case Axis.vertical:
        return widget.reverse ? AxisDirection.up : AxisDirection.down;
    }
  }

  Widget _buildCarouselItem(int index) {
    final CarouselViewThemeData carouselTheme = CarouselViewTheme.of(context);
    final ColorScheme colorScheme = ColorScheme.of(context);
    final EdgeInsets effectivePadding =
        widget.padding ?? carouselTheme.padding ?? const EdgeInsets.all(4.0);
    final Color effectiveBackgroundColor =
        widget.backgroundColor ?? carouselTheme.backgroundColor ?? colorScheme.surface;
    final double effectiveElevation = widget.elevation ?? carouselTheme.elevation ?? 0.0;
    final ShapeBorder effectiveShape =
        widget.shape ??
        carouselTheme.shape ??
        const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(28.0)));
    final Clip effectiveItemClipBehavior =
        widget.itemClipBehavior ?? carouselTheme.itemClipBehavior ?? Clip.antiAlias;
    final WidgetStateProperty<Color?> effectiveOverlayColor =
        widget.overlayColor ??
        carouselTheme.overlayColor ??
        WidgetStateProperty.resolveWith((Set<WidgetState> states) {
          if (states.contains(WidgetState.pressed)) {
            return colorScheme.onSurface.withOpacity(0.1);
          }
          if (states.contains(WidgetState.hovered)) {
            return colorScheme.onSurface.withOpacity(0.08);
          }
          if (states.contains(WidgetState.focused)) {
            return colorScheme.onSurface.withOpacity(0.1);
          }
          return null;
        });

    Widget contents = widget.children[index];

    if (widget.enableSplash) {
      contents = Stack(
        fit: StackFit.expand,
        children: <Widget>[
          contents,
          Material(
            color: Colors.transparent,
            child: InkWell(
              onTap: () => widget.onTap?.call(index),
              overlayColor: effectiveOverlayColor,
            ),
          ),
        ],
      );
    } else if (widget.onTap != null) {
      contents = GestureDetector(onTap: () => widget.onTap!(index), child: contents);
    }

    return Padding(
      padding: effectivePadding,
      child: Material(
        clipBehavior: effectiveItemClipBehavior,
        color: effectiveBackgroundColor,
        elevation: effectiveElevation,
        shape: effectiveShape,
        child: contents,
      ),
    );
  }

  Widget _buildSliverCarousel(ThemeData theme) {
    // Determine the child count and builder based on whether we're using lazy loading
    final int? childCount = widget.itemBuilder != null ? widget.itemCount : widget.children.length;
    final NullableIndexedWidgetBuilder effectiveBuilder = widget.itemBuilder != null
        ? widget.itemBuilder!
        : (BuildContext context, int index) => _buildCarouselItem(index);

    if (_itemExtent != null) {
      return _SliverFixedExtentCarousel(
        itemExtent: _itemExtent!,
        minExtent: widget.shrinkExtent,
        delegate: SliverChildBuilderDelegate(effectiveBuilder, childCount: childCount),
      );
    }

    assert(
      _flexWeights != null && _flexWeights!.every((int weight) => weight > 0),
      'flexWeights is null or it contains non-positive integers',
    );
    return _SliverWeightedCarousel(
      consumeMaxWeight: _consumeMaxWeight,
      shrinkExtent: widget.shrinkExtent,
      weights: _flexWeights!,
      delegate: SliverChildBuilderDelegate(effectiveBuilder, childCount: childCount),
    );
  }

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    final AxisDirection axisDirection = _getDirection(context);
    final ScrollPhysics physics = widget.itemSnapping
        ? const CarouselScrollPhysics()
        : ScrollConfiguration.of(context).getScrollPhysics(context);

    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) {
        final double mainAxisExtent = switch (widget.scrollDirection) {
          Axis.horizontal => constraints.maxWidth,
          Axis.vertical => constraints.maxHeight,
        };
        _itemExtent = widget.itemExtent == null
            ? null
            : clampDouble(widget.itemExtent!, 0, mainAxisExtent);
        return Scrollable(
          axisDirection: axisDirection,
          controller: _controller,
          physics: physics,
          viewportBuilder: (BuildContext context, ViewportOffset position) {
            return Viewport(
              scrollCacheExtent: const ScrollCacheExtent.viewport(0.0),
              axisDirection: axisDirection,
              offset: position,
              clipBehavior: Clip.antiAlias,
              slivers: <Widget>[_buildSliverCarousel(theme)],
            );
          },
        );
      },
    );
  }
}

/// A sliver that displays its box children in a linear array with a fixed extent
/// per item.
///
/// _To learn more about slivers, see [CustomScrollView.slivers]._
///
/// This sliver list arranges its children in a line along the main axis starting
/// at offset zero and without gaps. Each child is constrained to a fixed extent
/// along the main axis and the [SliverConstraints.crossAxisExtent]
/// along the cross axis. The difference between this and a list view with a fixed
/// extent is the first item and last item can be collapsed a little during scrolling
/// transition. This compression is controlled by the `minExtent` property and
/// aligns with the [Material Design Carousel specifications]
/// (https://m3.material.io/components/carousel/guidelines#96c5c157-fe5b-4ee3-a9b4-72bf8efab7e9).
class _SliverFixedExtentCarousel extends SliverMultiBoxAdaptorWidget {
  const _SliverFixedExtentCarousel({
    required super.delegate,
    required this.minExtent,
    required this.itemExtent,
  });

  final double itemExtent;
  final double minExtent;

  @override
  RenderSliverFixedExtentBoxAdaptor createRenderObject(BuildContext context) {
    final element = context as SliverMultiBoxAdaptorElement;
    return _RenderSliverFixedExtentCarousel(
      childManager: element,
      minExtent: minExtent,
      maxExtent: itemExtent,
    );
  }

  @override
  void updateRenderObject(BuildContext context, _RenderSliverFixedExtentCarousel renderObject) {
    renderObject.maxExtent = itemExtent;
    renderObject.minExtent = minExtent;
  }
}

class _RenderSliverFixedExtentCarousel extends RenderSliverFixedExtentBoxAdaptor {
  _RenderSliverFixedExtentCarousel({
    required super.childManager,
    required double maxExtent,
    required double minExtent,
  }) : _maxExtent = maxExtent,
       _minExtent = minExtent;

  double get maxExtent => _maxExtent;
  double _maxExtent;
  set maxExtent(double value) {
    if (_maxExtent == value) {
      return;
    }
    _maxExtent = value;
    markNeedsLayout();
  }

  double get minExtent => _minExtent;
  double _minExtent;
  set minExtent(double value) {
    if (_minExtent == value) {
      return;
    }
    _minExtent = value;
    markNeedsLayout();
  }

  // This implements the [itemExtentBuilder] callback.
  double _buildItemExtent(int index, SliverLayoutDimensions currentLayoutDimensions) {
    if (maxExtent == 0.0) {
      return maxExtent;
    }

    final int firstVisibleIndex = (constraints.scrollOffset / maxExtent).floor();

    // Calculate how many items have been completely scroll off screen.
    final int offscreenItems = (constraints.scrollOffset / maxExtent).floor();

    // If an item is partially off screen and partially on screen,
    // `constraints.scrollOffset` must be greater than
    // `offscreenItems * maxExtent`, so the difference between these two is how
    // much the current first visible item is off screen.
    final double offscreenExtent = constraints.scrollOffset - offscreenItems * maxExtent;

    // If there is not enough space to place the last visible item but the remaining
    // space is larger than `minExtent`, the extent for last item should be at
    // least the remaining extent to ensure a smooth size transition.
    final double effectiveMinExtent = math.max(
      constraints.remainingPaintExtent % maxExtent,
      minExtent,
    );

    // Two special cases are the first and last visible items. Other items' extent
    // should all return `maxExtent`.
    if (index == firstVisibleIndex) {
      final double effectiveExtent = maxExtent - offscreenExtent;
      return math.max(effectiveExtent, effectiveMinExtent);
    }

    final double scrollOffsetForLastIndex =
        constraints.scrollOffset + constraints.remainingPaintExtent;
    if (index == getMaxChildIndexForScrollOffset(scrollOffsetForLastIndex, maxExtent)) {
      return clampDouble(
        scrollOffsetForLastIndex - maxExtent * index,
        effectiveMinExtent,
        maxExtent,
      );
    }

    return maxExtent;
  }

  late SliverLayoutDimensions _currentLayoutDimensions;

  @override
  void performLayout() {
    _currentLayoutDimensions = SliverLayoutDimensions(
      scrollOffset: constraints.scrollOffset,
      precedingScrollExtent: constraints.precedingScrollExtent,
      viewportMainAxisExtent: constraints.viewportMainAxisExtent,
      crossAxisExtent: constraints.crossAxisExtent,
    );
    super.performLayout();
  }

  /// The layout offset for the child with the given index.
  @override
  double indexToLayoutOffset(
    @Deprecated(
      'The itemExtent is already available within the scope of this function. '
      'This feature was deprecated after v3.20.0-7.0.pre.',
    )
    double itemExtent,
    int index,
  ) {
    if (maxExtent == 0.0) {
      return maxExtent;
    }

    final int firstVisibleIndex = (constraints.scrollOffset / maxExtent).floor();

    // If there is not enough space to place the last visible item but the remaining
    // space is larger than `minExtent`, the extent for last item should be at
    // least the remaining extent to make sure a smooth size transition.
    final double effectiveMinExtent = math.max(
      constraints.remainingPaintExtent % maxExtent,
      minExtent,
    );
    if (index == firstVisibleIndex) {
      final double firstVisibleItemExtent = _buildItemExtent(index, _currentLayoutDimensions);

      // If the first item is collapsed to be less than `effectiveMinExtent`,
      // then it should stop changing its size and should start to scroll off screen.
      if (firstVisibleItemExtent <= effectiveMinExtent) {
        return maxExtent * index - effectiveMinExtent + maxExtent;
      }
      return constraints.scrollOffset;
    }
    return maxExtent * index;
  }

  /// The minimum child index that is visible at the given scroll offset.
  @override
  int getMinChildIndexForScrollOffset(
    double scrollOffset,
    @Deprecated(
      'The itemExtent is already available within the scope of this function. '
      'This feature was deprecated after v3.20.0-7.0.pre.',
    )
    double itemExtent,
  ) {
    if (maxExtent == 0.0) {
      return 0;
    }

    final int firstVisibleIndex = (constraints.scrollOffset / maxExtent).floor();
    return math.max(firstVisibleIndex, 0);
  }

  /// The maximum child index that is visible at the given scroll offset.
  @override
  int getMaxChildIndexForScrollOffset(
    double scrollOffset,
    @Deprecated(
      'The itemExtent is already available within the scope of this function. '
      'This feature was deprecated after v3.20.0-7.0.pre.',
    )
    double itemExtent,
  ) {
    if (maxExtent > 0.0) {
      final double actual = scrollOffset / maxExtent - 1;
      final int round = actual.round();
      if ((actual * maxExtent - round * maxExtent).abs() < precisionErrorTolerance) {
        return math.max(0, round);
      }
      return math.max(0, actual.ceil());
    }
    return 0;
  }

  @override
  double? get itemExtent => null;

  @override
  ItemExtentBuilder? get itemExtentBuilder => _buildItemExtent;
}

/// A sliver that arranges its box children in a linear array, constraining them
/// to specific weights determined by the [weights] property.
///
/// _To learn more about slivers, see [CustomScrollView.slivers]._
///
/// This sliver arranges its children in a line along the main axis, starting
/// at offset zero without gaps. Each child is constrained to its corresponding
/// weight along the main axis and to the [SliverConstraints.crossAxisExtent]
/// along the cross axis.
///
/// See [CarouselView.weighted] to get more calculation explanations.
class _SliverWeightedCarousel extends SliverMultiBoxAdaptorWidget {
  const _SliverWeightedCarousel({
    required super.delegate,
    required this.consumeMaxWeight,
    required this.shrinkExtent,
    required this.weights,
  });

  // Determine whether extra scroll offset should be calculate so that every
  // item have a chance to scroll to the maximum extent.
  //
  // This is useful when the leading/trailing items have smaller weights, such
  // as [1, 7], and [3, 2, 1].
  final bool consumeMaxWeight;

  // The starting extent for items when they gradually show on/off screen.
  //
  // This is useful to avoid a hairline shape. This value should also smaller
  // than the last item extent to make sure a smooth transition. So in calculation,
  // this is limited to [0, weight for the last visible item].
  final double shrinkExtent;

  // The layout arrangement.
  //
  // When items are laying out, each item will be arranged based on the order of
  // the weights and the extent is based on the corresponding weight out of the
  // sum of weights. The length of weights means how many items we can put in the
  // view at a time.
  final List<int> weights;

  @override
  RenderSliverFixedExtentBoxAdaptor createRenderObject(BuildContext context) {
    final element = context as SliverMultiBoxAdaptorElement;
    return _RenderSliverWeightedCarousel(
      childManager: element,
      consumeMaxWeight: consumeMaxWeight,
      shrinkExtent: shrinkExtent,
      weights: weights,
    );
  }

  @override
  void updateRenderObject(BuildContext context, _RenderSliverWeightedCarousel renderObject) {
    renderObject
      ..consumeMaxWeight = consumeMaxWeight
      ..shrinkExtent = shrinkExtent
      ..weights = weights;
  }
}

// A sliver that places its box children in a linear array and constrains them
// to have the corresponding weight which is determined by [weights].
class _RenderSliverWeightedCarousel extends RenderSliverFixedExtentBoxAdaptor {
  _RenderSliverWeightedCarousel({
    required super.childManager,
    required bool consumeMaxWeight,
    required double shrinkExtent,
    required List<int> weights,
  }) : _consumeMaxWeight = consumeMaxWeight,
       _shrinkExtent = shrinkExtent,
       _weights = weights;

  bool get consumeMaxWeight => _consumeMaxWeight;
  bool _consumeMaxWeight;
  set consumeMaxWeight(bool value) {
    if (_consumeMaxWeight == value) {
      return;
    }
    _consumeMaxWeight = value;
    markNeedsLayout();
  }

  double get shrinkExtent => _shrinkExtent;
  double _shrinkExtent;
  set shrinkExtent(double value) {
    if (_shrinkExtent == value) {
      return;
    }
    _shrinkExtent = value;
    markNeedsLayout();
  }

  List<int> get weights => _weights;
  List<int> _weights;
  set weights(List<int> value) {
    if (_weights == value) {
      return;
    }
    _weights = value;
    markNeedsLayout();
  }

  late SliverLayoutDimensions _currentLayoutDimensions;

  // This is to implement the itemExtentBuilder callback to return each item extent
  // while scrolling.
  //
  // The given `index` is compared with `_firstVisibleItemIndex` to know how
  // many items are placed before the current one in the view.
  double _buildItemExtent(int index, SliverLayoutDimensions currentLayoutDimensions) {
    // If constraints.viewportMainAxisExtent is 0, firstChildExtent will be 0 and cause division error.
    if (constraints.viewportMainAxisExtent == 0) {
      return 0;
    }

    double extent;
    if (index == _firstVisibleItemIndex) {
      extent = math.max(_distanceToLeadingEdge, effectiveShrinkExtent);
    }
    // Calculate the extents of items located within the range defined by the
    // weights array relative to the first visible item. This allows us to
    // precisely determine each item's extent based on its initial extent
    // (calculated from the weights) and the scrolling progress (the off-screen
    // portion of the first item).
    else if (index > _firstVisibleItemIndex &&
        index - _firstVisibleItemIndex + 1 <= weights.length) {
      assert(index - _firstVisibleItemIndex < weights.length);
      final int currIndexOnWeightList = index - _firstVisibleItemIndex;
      final int currWeight = weights[currIndexOnWeightList];
      extent = extentUnit * currWeight; // initial extent
      final double progress = _firstVisibleItemOffscreenExtent / firstChildExtent;

      final int prevWeight = weights[currIndexOnWeightList - 1];
      final double finalIncrease = (prevWeight - currWeight) / weights.max;
      extent = extent + finalIncrease * progress * maxChildExtent;
    }
    // Calculate the extents of items located beyond the range defined by the
    // weights array relative to the first visible item. During scrolling transition,
    // it is possible that the number of visible items is larger than the length
    // of `weights`. The extra item extent should be calculated here to fill
    // the remaining space.
    else if (index > _firstVisibleItemIndex &&
        index - _firstVisibleItemIndex + 1 > weights.length) {
      double visibleItemsTotalExtent = _distanceToLeadingEdge;
      for (int i = _firstVisibleItemIndex + 1; i < index; i++) {
        visibleItemsTotalExtent += _buildItemExtent(i, currentLayoutDimensions);
      }
      extent = math.max(
        constraints.remainingPaintExtent - visibleItemsTotalExtent,
        effectiveShrinkExtent,
      );
    } else {
      extent = math.max(minChildExtent, effectiveShrinkExtent);
    }
    return extent;
  }

  // To ge the extent unit based on the viewport extent and the sum of weights.
  double get extentUnit =>
      constraints.viewportMainAxisExtent /
      (weights.reduce((int total, int extent) => total + extent));

  double get firstChildExtent => weights.first * extentUnit;
  double get maxChildExtent => weights.max * extentUnit;
  double get minChildExtent => weights.min * extentUnit;

  // The shrink extent for first and last visible items should be no larger
  // than [minChildExtent] to ensure a smooth transition.
  double get effectiveShrinkExtent => clampDouble(shrinkExtent, 0, minChildExtent);

  // The index of the first visible item. The returned value can be negative when
  // the leading items with smaller weights need to be fully expanded. For example,
  // assuming a weights [1, 7, 1], when item 0 is expanding to the maximum size
  // (with weight 7), we leave some space before item 0 assuming there is another
  // item -1 as the first visible item.
  int get _firstVisibleItemIndex {
    // If constraints.viewportMainAxisExtent is 0, firstChildExtent will be 0 and cause division error.
    if (constraints.viewportMainAxisExtent == 0.0) {
      return 0;
    }
    var smallerWeightCount = 0;
    for (final int weight in weights) {
      if (weight == weights.max) {
        break;
      }
      smallerWeightCount += 1;
    }
    int index;

    final double actual = constraints.scrollOffset / firstChildExtent;
    final int round = (constraints.scrollOffset / firstChildExtent).round();
    if ((actual - round).abs() < precisionErrorTolerance) {
      index = round;
    } else {
      index = actual.floor();
    }
    return consumeMaxWeight ? index - smallerWeightCount : index;
  }

  // This value indicates the scrolling progress of items following the first
  // item. It informs them how much the first item has moved off-screen,
  // enabling them to adjust their sizes (grow or shrink) accordingly.
  double get _firstVisibleItemOffscreenExtent {
    // If constraints.viewportMainAxisExtent is 0, firstChildExtent will be 0 and cause division error.
    if (constraints.viewportMainAxisExtent == 0.0) {
      return 0;
    }
    int index;
    final double actual = constraints.scrollOffset / firstChildExtent;
    final int round = (constraints.scrollOffset / firstChildExtent).round();
    if ((actual - round).abs() < precisionErrorTolerance) {
      index = round;
    } else {
      index = actual.floor();
    }
    return constraints.scrollOffset - index * firstChildExtent;
  }

  // Given the off-screen extent for the first visible item, we can know the
  // on-screen extent for the first visible item.
  double get _distanceToLeadingEdge => firstChildExtent - _firstVisibleItemOffscreenExtent;

  // Given an index, this method returns the layout offset for the item. The `index`
  // is firstly compared to `_firstVisibleItemIndex` and compute the distance
  // between them, then compute all the current extents for items that are located
  // in front.
  @override
  double indexToLayoutOffset(
    @Deprecated(
      'The itemExtent is already available within the scope of this function. '
      'This feature was deprecated after v3.20.0-7.0.pre.',
    )
    double itemExtent,
    int index,
  ) {
    if (index == _firstVisibleItemIndex) {
      if (_distanceToLeadingEdge <= effectiveShrinkExtent) {
        return constraints.scrollOffset - effectiveShrinkExtent + _distanceToLeadingEdge;
      }
      return constraints.scrollOffset;
    }
    double visibleItemsTotalExtent = _distanceToLeadingEdge;
    for (int i = _firstVisibleItemIndex + 1; i < index; i++) {
      visibleItemsTotalExtent += _buildItemExtent(i, _currentLayoutDimensions);
    }
    return constraints.scrollOffset + visibleItemsTotalExtent;
  }

  @override
  int getMinChildIndexForScrollOffset(
    double scrollOffset,
    @Deprecated(
      'The itemExtent is already available within the scope of this function. '
      'This feature was deprecated after v3.20.0-7.0.pre.',
    )
    double itemExtent,
  ) {
    return math.max(_firstVisibleItemIndex, 0);
  }

  @override
  int getMaxChildIndexForScrollOffset(
    double scrollOffset,
    @Deprecated(
      'The itemExtent is already available within the scope of this function. '
      'This feature was deprecated after v3.20.0-7.0.pre.',
    )
    double itemExtent,
  ) {
    final int? childCount = childManager.estimatedChildCount;
    if (childCount != null) {
      double visibleItemsTotalExtent = _distanceToLeadingEdge;
      for (int i = _firstVisibleItemIndex + 1; i < childCount; i++) {
        visibleItemsTotalExtent += _buildItemExtent(i, _currentLayoutDimensions);
        if (visibleItemsTotalExtent >= constraints.viewportMainAxisExtent) {
          return i;
        }
      }
    }
    return childCount ?? 0;
  }

  @override
  double computeMaxScrollOffset(
    SliverConstraints constraints,
    @Deprecated(
      'The itemExtent is already available within the scope of this function. '
      'This feature was deprecated after v3.20.0-7.0.pre.',
    )
    double itemExtent,
  ) {
    return childManager.childCount * maxChildExtent;
  }

  BoxConstraints _getChildConstraints(int index) {
    final double extent = itemExtentBuilder!(index, _currentLayoutDimensions)!;
    return constraints.asBoxConstraints(minExtent: extent, maxExtent: extent);
  }

  // This method is mostly the same as its parent class [RenderSliverFixedExtentList].
  // The difference is when we allow some space before the leading items or after
  // the trailing items with smaller weights, we leave extra scroll offset.
  // TODO(quncCccccc): add the calculation for the extra scroll offset on the super class to simplify the implementation here.
  @override
  void performLayout() {
    assert(
      (itemExtent != null && itemExtentBuilder == null) ||
          (itemExtent == null && itemExtentBuilder != null),
    );
    assert(itemExtentBuilder != null || (itemExtent!.isFinite && itemExtent! >= 0));

    final SliverConstraints constraints = this.constraints;
    childManager.didStartLayout();
    childManager.setDidUnderflow(false);

    final double scrollOffset = constraints.scrollOffset + constraints.cacheOrigin;
    assert(scrollOffset >= 0.0);
    final double remainingExtent = constraints.remainingCacheExtent;
    assert(remainingExtent >= 0.0);
    final double targetEndScrollOffset = scrollOffset + remainingExtent;
    _currentLayoutDimensions = SliverLayoutDimensions(
      scrollOffset: constraints.scrollOffset,
      precedingScrollExtent: constraints.precedingScrollExtent,
      viewportMainAxisExtent: constraints.viewportMainAxisExtent,
      crossAxisExtent: constraints.crossAxisExtent,
    );
    // TODO(Piinks): Clean up when deprecation expires.
    const double deprecatedExtraItemExtent = -1;

    final int firstIndex = getMinChildIndexForScrollOffset(scrollOffset, deprecatedExtraItemExtent);
    final int? targetLastIndex = targetEndScrollOffset.isFinite
        ? getMaxChildIndexForScrollOffset(targetEndScrollOffset, deprecatedExtraItemExtent)
        : null;

    if (firstChild != null) {
      final int leadingGarbage = calculateLeadingGarbage(firstIndex: firstIndex);
      final int trailingGarbage = targetLastIndex != null
          ? calculateTrailingGarbage(lastIndex: targetLastIndex)
          : 0;
      collectGarbage(leadingGarbage, trailingGarbage);
    } else {
      collectGarbage(0, 0);
    }

    if (firstChild == null) {
      final double layoutOffset = indexToLayoutOffset(deprecatedExtraItemExtent, firstIndex);
      if (!addInitialChild(index: firstIndex, layoutOffset: layoutOffset)) {
        // There are either no children, or we are past the end of all our children.
        final double max;
        if (firstIndex <= 0) {
          max = 0.0;
        } else {
          max = computeMaxScrollOffset(constraints, deprecatedExtraItemExtent);
        }
        geometry = SliverGeometry(scrollExtent: max, maxPaintExtent: max);
        childManager.didFinishLayout();
        return;
      }
    }

    RenderBox? trailingChildWithLayout;

    for (int index = indexOf(firstChild!) - 1; index >= firstIndex; --index) {
      final RenderBox? child = insertAndLayoutLeadingChild(_getChildConstraints(index));
      if (child == null) {
        // Items before the previously first child are no longer present.
        // Reset the scroll offset to offset all items prior and up to the
        // missing item. Let parent re-layout everything.
        geometry = SliverGeometry(
          scrollOffsetCorrection: indexToLayoutOffset(deprecatedExtraItemExtent, index),
        );
        return;
      }
      final childParentData = child.parentData! as SliverMultiBoxAdaptorParentData;
      childParentData.layoutOffset = indexToLayoutOffset(deprecatedExtraItemExtent, index);
      assert(childParentData.index == index);
      trailingChildWithLayout ??= child;
    }

    if (trailingChildWithLayout == null) {
      firstChild!.layout(_getChildConstraints(indexOf(firstChild!)));
      final childParentData = firstChild!.parentData! as SliverMultiBoxAdaptorParentData;
      childParentData.layoutOffset = indexToLayoutOffset(deprecatedExtraItemExtent, firstIndex);
      trailingChildWithLayout = firstChild;
    }

    // From the last item to the firstly encountered max item
    double extraLayoutOffset = 0;
    if (consumeMaxWeight) {
      for (int i = weights.length - 1; i >= 0; i--) {
        if (weights[i] == weights.max) {
          break;
        }
        extraLayoutOffset += weights[i] * extentUnit;
      }
    }

    double estimatedMaxScrollOffset = double.infinity;
    // Layout visible items after the first visible item.
    for (
      int index = indexOf(trailingChildWithLayout!) + 1;
      targetLastIndex == null || index <= targetLastIndex;
      ++index
    ) {
      RenderBox? child = childAfter(trailingChildWithLayout!);
      if (child == null || indexOf(child) != index) {
        child = insertAndLayoutChild(_getChildConstraints(index), after: trailingChildWithLayout);
        if (child == null) {
          // We have run out of children.
          estimatedMaxScrollOffset =
              indexToLayoutOffset(deprecatedExtraItemExtent, index) + extraLayoutOffset;
          break;
        }
      } else {
        child.layout(_getChildConstraints(index));
      }
      trailingChildWithLayout = child;
      final childParentData = child.parentData! as SliverMultiBoxAdaptorParentData;
      assert(childParentData.index == index);
      childParentData.layoutOffset = indexToLayoutOffset(
        deprecatedExtraItemExtent,
        childParentData.index!,
      );
    }

    final int lastIndex = indexOf(lastChild!);
    final double leadingScrollOffset = indexToLayoutOffset(deprecatedExtraItemExtent, firstIndex);
    double trailingScrollOffset;

    if (lastIndex + 1 == childManager.childCount) {
      trailingScrollOffset = indexToLayoutOffset(deprecatedExtraItemExtent, lastIndex);

      trailingScrollOffset += math.max(
        weights.last * extentUnit,
        _buildItemExtent(lastIndex, _currentLayoutDimensions),
      );
      trailingScrollOffset += extraLayoutOffset;
    } else {
      trailingScrollOffset = indexToLayoutOffset(deprecatedExtraItemExtent, lastIndex + 1);
    }

    assert(debugAssertChildListIsNonEmptyAndContiguous());
    assert(indexOf(firstChild!) == firstIndex);
    assert(targetLastIndex == null || lastIndex <= targetLastIndex);

    estimatedMaxScrollOffset = math.min(
      estimatedMaxScrollOffset,
      estimateMaxScrollOffset(
        constraints,
        firstIndex: firstIndex,
        lastIndex: lastIndex,
        leadingScrollOffset: leadingScrollOffset,
        trailingScrollOffset: trailingScrollOffset,
      ),
    );

    final double paintExtent = calculatePaintOffset(
      constraints,
      from: consumeMaxWeight ? 0 : leadingScrollOffset,
      to: trailingScrollOffset,
    );

    final double cacheExtent = calculateCacheOffset(
      constraints,
      from: consumeMaxWeight ? 0 : leadingScrollOffset,
      to: trailingScrollOffset,
    );

    final double targetEndScrollOffsetForPaint =
        constraints.scrollOffset + constraints.remainingPaintExtent;
    final int? targetLastIndexForPaint = targetEndScrollOffsetForPaint.isFinite
        ? getMaxChildIndexForScrollOffset(targetEndScrollOffsetForPaint, deprecatedExtraItemExtent)
        : null;

    geometry = SliverGeometry(
      scrollExtent: estimatedMaxScrollOffset,
      paintExtent: paintExtent,
      cacheExtent: cacheExtent,
      maxPaintExtent: estimatedMaxScrollOffset,
      // Conservative to avoid flickering away the clip during scroll.
      hasVisualOverflow:
          (targetLastIndexForPaint != null && lastIndex >= targetLastIndexForPaint) ||
          constraints.scrollOffset > 0.0,
    );

    // We may have started the layout while scrolled to the end, which would not
    // expose a new child.
    if (estimatedMaxScrollOffset == trailingScrollOffset) {
      childManager.setDidUnderflow(true);
    }
    childManager.didFinishLayout();
  }

  @override
  double? get itemExtent => null;

  /// The main-axis extent builder of each item.
  ///
  /// If this is non-null, the [itemExtent] must be null.
  /// If this is null, the [itemExtent] must be non-null.
  @override
  ItemExtentBuilder? get itemExtentBuilder => _buildItemExtent;
}

/// Scroll physics used by a [CarouselView].
///
/// These physics cause the carousel item to snap to item boundaries.
///
/// See also:
///
///  * [ScrollPhysics], the base class which defines the API for scrolling
///    physics.
///  * [PageScrollPhysics], scroll physics used by a [PageView].
class CarouselScrollPhysics extends ScrollPhysics {
  /// Creates physics for a [CarouselView].
  const CarouselScrollPhysics({super.parent});

  @override
  CarouselScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return CarouselScrollPhysics(parent: buildParent(ancestor));
  }

  double _getTargetPixels(_CarouselPosition position, Tolerance tolerance, double velocity) {
    double fraction;

    if (position.itemExtent != null) {
      fraction = position.itemExtent! / position.viewportDimension;
    } else {
      assert(position.flexWeights != null);
      fraction = position.flexWeights!.first / position.flexWeights!.sum;
    }

    final double itemWidth = position.viewportDimension * fraction;

    final double actual = math.max(0.0, position.pixels) / itemWidth;
    final double round = actual.roundToDouble();
    double item;
    if ((actual - round).abs() < precisionErrorTolerance) {
      item = round;
    } else {
      item = actual;
    }
    if (velocity < -tolerance.velocity) {
      item -= 0.5;
    } else if (velocity > tolerance.velocity) {
      item += 0.5;
    }
    return item.roundToDouble() * itemWidth;
  }

  @override
  Simulation? createBallisticSimulation(ScrollMetrics position, double velocity) {
    assert(
      position is _CarouselPosition,
      'CarouselScrollPhysics can only be used with Scrollables that uses '
      'the CarouselController',
    );

    final metrics = position as _CarouselPosition;
    if ((velocity <= 0.0 && metrics.pixels <= metrics.minScrollExtent) ||
        (velocity >= 0.0 && metrics.pixels >= metrics.maxScrollExtent)) {
      return super.createBallisticSimulation(metrics, velocity);
    }

    final Tolerance tolerance = toleranceFor(metrics);
    final double target = _getTargetPixels(metrics, tolerance, velocity);
    if (target != metrics.pixels) {
      return ScrollSpringSimulation(spring, metrics.pixels, target, velocity, tolerance: tolerance);
    }
    return null;
  }

  @override
  bool get allowImplicitScrolling => true;
}

/// Metrics for a [CarouselView].
class _CarouselMetrics extends FixedScrollMetrics {
  /// Creates an immutable snapshot of values associated with a [CarouselView].
  _CarouselMetrics({
    required super.minScrollExtent,
    required super.maxScrollExtent,
    required super.pixels,
    required super.viewportDimension,
    required super.axisDirection,
    this.itemExtent,
    this.flexWeights,
    this.consumeMaxWeight,
    required super.devicePixelRatio,
  });

  /// Extent for the carousel item.
  ///
  /// Used to compute the first item from the current [pixels].
  final double? itemExtent;

  /// The fraction of the viewport that the first item occupies.
  ///
  /// Used to compute the extent of each carousel item from the current [pixels],
  /// if [itemExtent] is null.
  final List<int>? flexWeights;

  /// Determine whether each child can be expanded to occupy the maximum weight while scrolling.
  final bool? consumeMaxWeight;

  @override
  _CarouselMetrics copyWith({
    double? minScrollExtent,
    double? maxScrollExtent,
    double? pixels,
    double? viewportDimension,
    AxisDirection? axisDirection,
    double? itemExtent,
    List<int>? flexWeights,
    bool? consumeMaxWeight,
    double? devicePixelRatio,
  }) {
    return _CarouselMetrics(
      minScrollExtent: minScrollExtent ?? (hasContentDimensions ? this.minScrollExtent : null),
      maxScrollExtent: maxScrollExtent ?? (hasContentDimensions ? this.maxScrollExtent : null),
      pixels: pixels ?? (hasPixels ? this.pixels : null),
      viewportDimension:
          viewportDimension ?? (hasViewportDimension ? this.viewportDimension : null),
      axisDirection: axisDirection ?? this.axisDirection,
      itemExtent: itemExtent ?? this.itemExtent,
      flexWeights: flexWeights ?? this.flexWeights,
      consumeMaxWeight: consumeMaxWeight ?? this.consumeMaxWeight,
      devicePixelRatio: devicePixelRatio ?? this.devicePixelRatio,
    );
  }
}

class _CarouselPosition extends ScrollPositionWithSingleContext implements _CarouselMetrics {
  _CarouselPosition({
    required super.physics,
    required super.context,
    this.initialItem = 0,
    double? itemExtent,
    List<int>? flexWeights,
    bool consumeMaxWeight = true,
    super.oldPosition,
  }) : assert(
         flexWeights != null && itemExtent == null || flexWeights == null && itemExtent != null,
       ),
       _itemToShowOnStartup = initialItem.toDouble(),
       _consumeMaxWeight = consumeMaxWeight,
       super(initialPixels: null);

  int initialItem;
  final double _itemToShowOnStartup;
  // When the viewport has a zero-size, the item can not
  // be retrieved by `getItemFromPixels`, so we need to cache the item
  // for use when resizing the viewport to non-zero next time.
  double? _cachedItem;

  @override
  bool get consumeMaxWeight => _consumeMaxWeight;
  bool _consumeMaxWeight;
  set consumeMaxWeight(bool value) {
    if (_consumeMaxWeight == value) {
      return;
    }
    if (hasPixels && flexWeights != null) {
      final double leadingItem = updateLeadingItem(flexWeights, value);
      final double newPixel = getPixelsFromItem(leadingItem, flexWeights, itemExtent);
      forcePixels(newPixel);
    }
    _consumeMaxWeight = value;
  }

  @override
  double? get itemExtent => _itemExtent;
  double? _itemExtent;
  set itemExtent(double? value) {
    if (_itemExtent == value) {
      return;
    }
    if (hasPixels && _itemExtent != null && viewportDimension != 0.0) {
      final double leadingItem = getItemFromPixels(pixels, viewportDimension);
      final double newPixel = getPixelsFromItem(leadingItem, flexWeights, value);
      forcePixels(newPixel);
    }
    _itemExtent = value;
  }

  @override
  List<int>? get flexWeights => _flexWeights;
  List<int>? _flexWeights;
  set flexWeights(List<int>? value) {
    if (flexWeights == value) {
      return;
    }
    final List<int>? oldWeights = _flexWeights;
    if (hasPixels && oldWeights != null) {
      final double leadingItem = updateLeadingItem(value, consumeMaxWeight);
      final double newPixel = getPixelsFromItem(leadingItem, value, itemExtent);
      forcePixels(newPixel);
    }
    _flexWeights = value;
  }

  // The index of the leading item in the carousel.
  // `getItemFromPixels` may return a fractional value (e.g., 0.6 when mid-scroll).
  // Use `toInt()` to truncate the fractional part, ensuring the leading item
  // only advances after fully crossing the next item's boundary.
  int get leadingItem {
    final int leadingItem = getItemFromPixels(pixels, viewportDimension).toInt();
    // When `consumeMaxWeight` is true, there is some reserved space before
    // item 0 so that item 0 can be expanded to occupy the maximum
    // weight while scrolling. The way how consumeMaxWeight works is that we assume
    // there are some "invisible" items before the first visible item. Therefore,
    // to calculate the correct visible leading item, we need to offset the leading
    // item by the index of the maximum weight.
    //
    // The subtraction may cause negative number for leading item. In this case,
    // constrain the leading item to 0.
    if (consumeMaxWeight && flexWeights != null) {
      return math.max(leadingItem - flexWeights!.indexOf(flexWeights!.max), 0);
    }
    return leadingItem;
  }

  double updateLeadingItem(List<int>? newFlexWeights, bool newConsumeMaxWeight) {
    final double maxItem;
    if (hasPixels && flexWeights != null) {
      final double leadingItem = getItemFromPixels(pixels, viewportDimension);
      maxItem = consumeMaxWeight
          ? leadingItem
          : leadingItem + flexWeights!.indexOf(flexWeights!.max);
    } else {
      maxItem = _itemToShowOnStartup;
    }
    if (newFlexWeights != null && !newConsumeMaxWeight) {
      var smallerWeights = 0;
      for (final int weight in newFlexWeights) {
        if (weight == newFlexWeights.max) {
          break;
        }
        smallerWeights += 1;
      }
      return maxItem - smallerWeights;
    }
    return maxItem;
  }

  double getItemFromPixels(double pixels, double viewportDimension) {
    assert(viewportDimension > 0.0);
    double fraction;
    if (itemExtent != null) {
      fraction = itemExtent! / viewportDimension;
    } else {
      // If itemExtent is null, flexWeights cannot be null.
      assert(flexWeights != null);
      fraction = flexWeights!.first / flexWeights!.sum;
    }

    final double actual = math.max(0.0, pixels) / (viewportDimension * fraction);
    final double round = actual.roundToDouble();
    if ((actual - round).abs() < precisionErrorTolerance) {
      return round;
    }
    return actual;
  }

  double getPixelsFromItem(double item, List<int>? flexWeights, double? itemExtent) {
    double fraction;
    if (viewportDimension == 0.0) {
      return 0.0;
    }
    if (itemExtent != null) {
      fraction = itemExtent / viewportDimension;
    } else {
      // If itemExtent is null, flexWeights cannot be null.
      assert(flexWeights != null);
      fraction = flexWeights!.first / flexWeights.sum;
    }

    return item * viewportDimension * fraction;
  }

  @override
  bool applyViewportDimension(double viewportDimension) {
    final double? oldViewportDimensions = hasViewportDimension ? this.viewportDimension : null;
    if (viewportDimension == oldViewportDimensions) {
      return true;
    }
    final bool result = super.applyViewportDimension(viewportDimension);
    final double? oldPixels = hasPixels ? pixels : null;
    double item;
    if (oldPixels == null) {
      item = updateLeadingItem(flexWeights, consumeMaxWeight);
    } else if (oldViewportDimensions == 0.0) {
      // If resize from zero, we should use the _cachedItem to recover the state.
      item = _cachedItem!;
    } else {
      item = getItemFromPixels(oldPixels, oldViewportDimensions ?? viewportDimension);
    }
    final double newPixels = getPixelsFromItem(item, flexWeights, itemExtent);
    // If the viewportDimension is zero, cache the item
    // in case the viewport is resized to be non-zero.
    _cachedItem = (viewportDimension == 0.0) ? item : null;

    if (newPixels != oldPixels) {
      correctPixels(newPixels);
      return false;
    }
    return result;
  }

  @override
  void absorb(ScrollPosition other) {
    super.absorb(other);

    if (other is! _CarouselPosition) {
      return;
    }

    _cachedItem = other._cachedItem;
    _itemExtent = other._itemExtent;
  }

  @override
  _CarouselMetrics copyWith({
    double? minScrollExtent,
    double? maxScrollExtent,
    double? pixels,
    double? viewportDimension,
    AxisDirection? axisDirection,
    double? itemExtent,
    List<int>? flexWeights,
    bool? consumeMaxWeight,
    double? devicePixelRatio,
  }) {
    return _CarouselMetrics(
      minScrollExtent: minScrollExtent ?? (hasContentDimensions ? this.minScrollExtent : null),
      maxScrollExtent: maxScrollExtent ?? (hasContentDimensions ? this.maxScrollExtent : null),
      pixels: pixels ?? (hasPixels ? this.pixels : null),
      viewportDimension:
          viewportDimension ?? (hasViewportDimension ? this.viewportDimension : null),
      axisDirection: axisDirection ?? this.axisDirection,
      itemExtent: itemExtent ?? this.itemExtent,
      flexWeights: flexWeights ?? this.flexWeights,
      consumeMaxWeight: consumeMaxWeight ?? this.consumeMaxWeight,
      devicePixelRatio: devicePixelRatio ?? this.devicePixelRatio,
    );
  }
}

/// A controller for [CarouselView].
///
/// Using a carousel controller helps to show the first visible item on the
/// carousel list.
class CarouselController extends ScrollController {
  /// Creates a carousel controller.
  CarouselController({this.initialItem = 0});

  /// The item that expands to the maximum size when first creating the [CarouselView].
  final int initialItem;

  /// The current leading item index in the [CarouselView].
  ///
  /// {@macro flutter.material.CarouselView.onIndexChanged}
  int get leadingItem {
    assert(
      positions.isNotEmpty,
      'CarouselController.leadingItem cannot be accessed before a CarouselView is built with it.',
    );
    assert(
      positions.length == 1,
      'CarouselController.leadingItem cannot be read when multiple CarouselViews '
      'are attached to the same controller.',
    );
    return (position as _CarouselPosition).leadingItem;
  }

  _CarouselViewState? _carouselState;

  // ignore: use_setters_to_change_properties
  void _attach(_CarouselViewState anchor) {
    _carouselState = anchor;
  }

  void _detach(_CarouselViewState anchor) {
    if (_carouselState == anchor) {
      _carouselState = null;
    }
  }

  /// Animates the controlled carousel to the given item index.
  ///
  /// For [CarouselView], this will scroll the carousel so the item at [index] becomes
  /// the leading item.
  ///
  /// If the [index] is less than 0, the carousel will scroll to the first item.
  /// If the [index] is greater than the number of items, the carousel will scroll
  /// to the last item.
  ///
  /// For [CarouselView.weighted], animates to make the item at [index] occupy the primary,
  /// most prominent position determined by the largest weight in `flexWeights`.
  ///
  /// The animation uses the provided [Duration] and [Curve]. The returned [Future]
  /// completes when the animation finishes.
  ///
  /// The [Duration] defaults to 300 milliseconds and [Curve] defaults to [Curves.ease].
  ///
  /// Does nothing if the carousel is not attached to this controller.
  Future<void> animateToItem(
    int index, {
    Duration duration = const Duration(milliseconds: 300),
    Curve curve = Curves.ease,
  }) async {
    if (!hasClients || _carouselState == null) {
      return;
    }

    final bool hasFlexWeights = _carouselState!._flexWeights?.isNotEmpty ?? false;
    if (_carouselState!.widget.itemBuilder != null) {
      final int? itemCount = _carouselState!.widget.itemCount;
      index = itemCount != null ? index.clamp(0, itemCount - 1) : 0;
    } else {
      index = index.clamp(0, _carouselState!.widget.children.length - 1);
    }

    await Future.wait<void>(<Future<void>>[
      for (final _CarouselPosition position in positions.cast<_CarouselPosition>())
        position.animateTo(
          _getTargetOffset(position, index, hasFlexWeights),
          duration: duration,
          curve: curve,
        ),
    ]);
  }

  double _getTargetOffset(_CarouselPosition position, int index, bool hasFlexWeights) {
    if (!hasFlexWeights) {
      return index * _carouselState!._itemExtent!;
    }

    final _CarouselViewState carouselState = _carouselState!;
    final List<int> weights = carouselState._flexWeights!;
    final int totalWeight = weights.reduce((int a, int b) => a + b);
    final double dimension = position.viewportDimension;

    final int maxWeightIndex = weights.indexOf(weights.max);
    int leadingIndex = carouselState._consumeMaxWeight ? index : index - maxWeightIndex;
    if (carouselState.widget.itemBuilder != null) {
      final int? itemCount = carouselState.widget.itemCount;
      leadingIndex = itemCount != null ? leadingIndex.clamp(0, itemCount - 1) : 0;
    } else {
      final int itemCount = carouselState.widget.children.length;
      leadingIndex = leadingIndex.clamp(0, itemCount - 1);
    }

    return dimension * (weights.first / totalWeight) * leadingIndex;
  }

  @override
  ScrollPosition createScrollPosition(
    ScrollPhysics physics,
    ScrollContext context,
    ScrollPosition? oldPosition,
  ) {
    assert(_carouselState != null);
    return _CarouselPosition(
      physics: physics,
      context: context,
      initialItem: initialItem,
      itemExtent: _carouselState!._itemExtent,
      consumeMaxWeight: _carouselState!._consumeMaxWeight,
      flexWeights: _carouselState!._flexWeights,
      oldPosition: oldPosition,
    );
  }

  @override
  void attach(ScrollPosition position) {
    super.attach(position);
    final carouselPosition = position as _CarouselPosition;
    carouselPosition.flexWeights = _carouselState!._flexWeights;
    carouselPosition.itemExtent = _carouselState!._itemExtent;
    carouselPosition.consumeMaxWeight = _carouselState!._consumeMaxWeight;
  }
}
