// 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 'route.dart';
/// @docImport 'text_theme.dart';
library;

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

import 'colors.dart';
import 'theme.dart';

// Eyeballed values comparing with a native picker to produce the right
// curvatures and densities.
const double _kDefaultDiameterRatio = 1.07;
const double _kDefaultPerspective = 0.003;
const double _kSqueeze = 1.45;

// Opacity fraction value that dims the wheel above and below the "magnifier"
// lens.
const double _kOverAndUnderCenterOpacity = 0.447;

// The duration and curve of the tap-to-scroll gesture's animation when a picker
// item is tapped.
//
// Eyeballed from an iPhone 15 Pro simulator running iOS 17.5.
const Duration _kCupertinoPickerTapToScrollDuration = Duration(milliseconds: 300);
const Curve _kCupertinoPickerTapToScrollCurve = Curves.easeInOut;

/// An iOS-styled picker.
///
/// Displays its children widgets on a wheel for selection and
/// calls back when the currently selected item changes.
///
/// By default, the first child in `children` will be the initially selected child.
/// The index of a different child can be specified in [scrollController], to make
/// that child the initially selected child.
///
/// Can be used with [showCupertinoModalPopup] to display the picker modally at the
/// bottom of the screen. When calling [showCupertinoModalPopup], be sure to set
/// `semanticsDismissible` to true to enable dismissing the modal via semantics.
///
/// Sizes itself to its parent. All children are sized to the same size based
/// on [itemExtent].
///
/// By default, descendent texts are shown with [CupertinoTextThemeData.pickerTextStyle].
///
/// {@tool dartpad}
/// This example shows a [CupertinoPicker] that displays a list of fruits on a wheel for
/// selection.
///
/// ** See code in examples/api/lib/cupertino/picker/cupertino_picker.0.dart **
/// {@end-tool}
///
/// See also:
///
///  * [ListWheelScrollView], the generic widget backing this picker without
///    the iOS design specific chrome.
///  * <https://developer.apple.com/design/human-interface-guidelines/pickers/>
class CupertinoPicker extends StatefulWidget {
  /// Creates a picker from a concrete list of children.
  ///
  /// The [itemExtent] must be greater than zero.
  ///
  /// The [backgroundColor] defaults to null, which disables background painting entirely.
  /// (i.e. the picker is going to have a completely transparent background), to match
  /// the native UIPicker and UIDatePicker. Also, if it has transparency, no gradient
  /// effect will be rendered.
  ///
  /// The [scrollController] argument can be used to specify a custom
  /// [FixedExtentScrollController] for programmatically reading or changing
  /// the current picker index or for selecting an initial index value.
  ///
  /// The [looping] argument decides whether the child list loops and can be
  /// scrolled infinitely. If set to true, scrolling past the end of the list
  /// will loop the list back to the beginning. If set to false, the list will
  /// stop scrolling when you reach the end or the beginning.
  CupertinoPicker({
    super.key,
    this.diameterRatio = _kDefaultDiameterRatio,
    this.backgroundColor,
    this.offAxisFraction = 0.0,
    this.useMagnifier = false,
    this.magnification = 1.0,
    this.scrollController,
    this.squeeze = _kSqueeze,
    this.changeReportingBehavior = ChangeReportingBehavior.onScrollUpdate,
    required this.itemExtent,
    required this.onSelectedItemChanged,
    required List<Widget> children,
    this.selectionOverlay = const CupertinoPickerDefaultSelectionOverlay(),
    bool looping = false,
  }) : assert(diameterRatio > 0.0, RenderListWheelViewport.diameterRatioZeroMessage),
       assert(magnification > 0),
       assert(itemExtent > 0),
       assert(squeeze > 0),
       childDelegate = looping
           ? ListWheelChildLoopingListDelegate(children: children)
           : ListWheelChildListDelegate(children: children);

  /// Creates a picker from an [IndexedWidgetBuilder] callback where the builder
  /// is dynamically invoked during layout.
  ///
  /// A child is lazily created when it starts becoming visible in the viewport.
  /// All of the children provided by the builder are cached and reused, so
  /// normally the builder is only called once for each index (except when
  /// rebuilding - the cache is cleared).
  ///
  /// The [childCount] argument reflects the number of children that will be
  /// provided by the [itemBuilder].
  /// {@macro flutter.widgets.ListWheelChildBuilderDelegate.childCount}
  ///
  /// The [itemExtent] argument must be positive.
  ///
  /// The [backgroundColor] defaults to null, which disables background painting entirely.
  /// (i.e. the picker is going to have a completely transparent background), to match
  /// the native UIPicker and UIDatePicker.
  CupertinoPicker.builder({
    super.key,
    this.diameterRatio = _kDefaultDiameterRatio,
    this.backgroundColor,
    this.offAxisFraction = 0.0,
    this.useMagnifier = false,
    this.magnification = 1.0,
    this.scrollController,
    this.squeeze = _kSqueeze,
    this.changeReportingBehavior = ChangeReportingBehavior.onScrollUpdate,
    required this.itemExtent,
    required this.onSelectedItemChanged,
    required NullableIndexedWidgetBuilder itemBuilder,
    int? childCount,
    this.selectionOverlay = const CupertinoPickerDefaultSelectionOverlay(),
  }) : assert(diameterRatio > 0.0, RenderListWheelViewport.diameterRatioZeroMessage),
       assert(magnification > 0),
       assert(itemExtent > 0),
       assert(squeeze > 0),
       childDelegate = ListWheelChildBuilderDelegate(builder: itemBuilder, childCount: childCount);

  /// Relative ratio between this picker's height and the simulated cylinder's diameter.
  ///
  /// Smaller values creates more pronounced curvatures in the scrollable wheel.
  ///
  /// For more details, see [ListWheelScrollView.diameterRatio].
  ///
  /// Defaults to 1.1 to visually mimic iOS.
  final double diameterRatio;

  /// Background color behind the children.
  ///
  /// Defaults to null, which disables background painting entirely.
  /// (i.e. the picker is going to have a completely transparent background), to match
  /// the native UIPicker and UIDatePicker.
  ///
  /// Any alpha value less 255 (fully opaque) will cause the removal of the
  /// wheel list edge fade gradient from rendering of the widget.
  final Color? backgroundColor;

  /// {@macro flutter.rendering.RenderListWheelViewport.offAxisFraction}
  final double offAxisFraction;

  /// {@macro flutter.rendering.RenderListWheelViewport.useMagnifier}
  final bool useMagnifier;

  /// {@macro flutter.rendering.RenderListWheelViewport.magnification}
  final double magnification;

  /// A [FixedExtentScrollController] to read and control the current item, and
  /// to set the initial item.
  ///
  /// If null, an implicit one will be created internally.
  final FixedExtentScrollController? scrollController;

  /// {@template flutter.cupertino.picker.itemExtent}
  /// The uniform height of all children.
  ///
  /// All children will be given the [BoxConstraints] to match this exact
  /// height. Must be a positive value.
  /// {@endtemplate}
  final double itemExtent;

  /// {@macro flutter.rendering.RenderListWheelViewport.squeeze}
  ///
  /// Defaults to `1.45` to visually mimic iOS.
  final double squeeze;

  /// The behavior of reporting the selected item index.
  ///
  /// This determines when the [onSelectedItemChanged] callback is called.
  ///
  /// Native iOS 18 behavior is [ChangeReportingBehavior.onScrollEnd], which
  /// calls the callback only when the scrolling stops.
  ///
  /// Defaults to [ChangeReportingBehavior.onScrollUpdate].
  final ChangeReportingBehavior changeReportingBehavior;

  /// Called when the selected item changes.
  ///
  /// The timing of this callback is controlled by [changeReportingBehavior].
  final ValueChanged<int>? onSelectedItemChanged;

  /// A delegate that lazily instantiates children.
  final ListWheelChildDelegate childDelegate;

  /// A widget overlaid on the picker to highlight the currently selected entry.
  ///
  /// The [selectionOverlay] widget drawn above the [CupertinoPicker]'s picker
  /// wheel.
  /// It is vertically centered in the picker and is constrained to have the
  /// same height as the center row.
  ///
  /// If unspecified, it defaults to a [CupertinoPickerDefaultSelectionOverlay]
  /// which is a gray rounded rectangle overlay in iOS 14 style.
  /// This property can be set to null to remove the overlay.
  final Widget? selectionOverlay;

  @override
  State<StatefulWidget> createState() => _CupertinoPickerState();
}

class _CupertinoPickerState extends State<CupertinoPicker> {
  // Initial value set to skip haptic feedback for the first item.
  late int _lastHapticIndex = _effectiveController.initialItem;
  int? _lastMiddlePosition;
  FixedExtentScrollController? _controller;
  bool _enableHapticFeedback = true;

  FixedExtentScrollController get _effectiveController => widget.scrollController ?? _controller!;

  @override
  void initState() {
    super.initState();
    if (widget.scrollController == null) {
      _controller = FixedExtentScrollController();
    }

    _effectiveController.addListener(_handleScroll);
  }

  @override
  void didUpdateWidget(CupertinoPicker oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.scrollController != null && oldWidget.scrollController == null) {
      _controller?.dispose();
      _controller = null;
      widget.scrollController!.addListener(_handleScroll);
    } else if (widget.scrollController == null && oldWidget.scrollController != null) {
      assert(_controller == null);
      oldWidget.scrollController!.removeListener(_handleScroll);
      _controller = FixedExtentScrollController();
      _controller!.addListener(_handleScroll);
    }
  }

  @override
  void dispose() {
    _controller?.dispose();
    if (widget.scrollController != null) {
      widget.scrollController!.removeListener(_handleScroll);
    }
    super.dispose();
  }

  void _handleHapticFeedback(int index) {
    if (!_enableHapticFeedback) {
      return;
    }
    switch (defaultTargetPlatform) {
      case TargetPlatform.iOS:
        if (index != _lastHapticIndex) {
          _lastHapticIndex = index;
          HapticFeedback.selectionClick();
          SystemSound.play(SystemSoundType.tick);
        }
      case TargetPlatform.android:
      case TargetPlatform.fuchsia:
      case TargetPlatform.linux:
      case TargetPlatform.macOS:
      case TargetPlatform.windows:
        // No haptic feedback on these platforms.
        return;
    }
  }

  void _handleScroll() {
    final int index = _effectiveController.selectedItem;

    // This switches from the current index to the next index
    // when we pass the middle of the item.
    final double fractionalOffset = _effectiveController.offset / widget.itemExtent;
    final int currentPosition = fractionalOffset.floor();

    final double currentItemOffset = fractionalOffset - index;
    // Check that we either passed in the middle of the new item or
    // that we are very close.
    // The second check is to avoid the rounding error when the
    // scroll position is very close to the middle of the item,
    // but not exactly in the middle.
    if (currentPosition != _lastMiddlePosition || currentItemOffset.abs() <= 0.1) {
      // Middle is checked with currentPosition, but we pass the real index
      // to avoid multiple haptics for the same item and to avoid
      // calling haptic feedback when overscrolling.
      _handleHapticFeedback(index);
    }

    _lastMiddlePosition = currentPosition;
  }

  Future<void> _handleChildTap(int index) async {
    _enableHapticFeedback = false;
    await _effectiveController.animateToItem(
      index,
      duration: _kCupertinoPickerTapToScrollDuration,
      curve: _kCupertinoPickerTapToScrollCurve,
    );
    _enableHapticFeedback = true;
    _lastHapticIndex = _effectiveController.selectedItem;
  }

  /// Draws the selectionOverlay.
  Widget _buildSelectionOverlay(Widget selectionOverlay) {
    final double height = widget.itemExtent * widget.magnification;

    return IgnorePointer(
      child: Center(
        child: ConstrainedBox(
          constraints: BoxConstraints.expand(height: height),
          child: selectionOverlay,
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final TextStyle textStyle = CupertinoTheme.of(context).textTheme.pickerTextStyle;
    final Color? resolvedBackgroundColor = CupertinoDynamicColor.maybeResolve(
      widget.backgroundColor,
      context,
    );

    assert(RenderListWheelViewport.defaultPerspective == _kDefaultPerspective);
    final Widget result = DefaultTextStyle(
      style: textStyle.copyWith(
        color: CupertinoDynamicColor.maybeResolve(textStyle.color, context),
      ),
      child: Stack(
        children: <Widget>[
          Positioned.fill(
            child: _CupertinoPickerSemantics(
              scrollController: _effectiveController,
              child: ListWheelScrollView.useDelegate(
                controller: _effectiveController,
                physics: const FixedExtentScrollPhysics(),
                diameterRatio: widget.diameterRatio,
                offAxisFraction: widget.offAxisFraction,
                useMagnifier: widget.useMagnifier,
                magnification: widget.magnification,
                overAndUnderCenterOpacity: _kOverAndUnderCenterOpacity,
                itemExtent: widget.itemExtent,
                squeeze: widget.squeeze,
                onSelectedItemChanged: widget.onSelectedItemChanged,
                dragStartBehavior: DragStartBehavior.down,
                changeReportingBehavior: widget.changeReportingBehavior,
                childDelegate: _CupertinoPickerListWheelChildDelegateWrapper(
                  widget.childDelegate,
                  onTappedChild: _handleChildTap,
                ),
              ),
            ),
          ),
          if (widget.selectionOverlay != null) _buildSelectionOverlay(widget.selectionOverlay!),
        ],
      ),
    );

    return DecoratedBox(
      decoration: BoxDecoration(color: resolvedBackgroundColor),
      child: result,
    );
  }
}

/// A default selection overlay for [CupertinoPicker]s.
///
/// It draws a gray rounded rectangle to match the picker visuals introduced in
/// iOS 14.
///
/// This widget is typically only used in [CupertinoPicker.selectionOverlay].
/// In an iOS 14 multi-column picker, the selection overlay is a single rounded
/// rectangle that spans the entire multi-column picker.
/// To achieve the same effect using [CupertinoPickerDefaultSelectionOverlay],
/// the additional margin and corner radii on the left or the right side can be
/// disabled by turning off [capStartEdge] and [capEndEdge], so this selection
/// overlay visually connects with selection overlays of adjoining
/// [CupertinoPicker]s (i.e., other "column"s).
///
/// See also:
///
///  * [CupertinoPicker], which uses this widget as its default [CupertinoPicker.selectionOverlay].
class CupertinoPickerDefaultSelectionOverlay extends StatelessWidget {
  /// Creates an iOS 14 style selection overlay that highlights the magnified
  /// area (or the currently selected item, depending on how you described it
  /// elsewhere) of a [CupertinoPicker].
  ///
  /// The [background] argument default value is
  /// [CupertinoColors.tertiarySystemFill].
  ///
  /// The [capStartEdge] and [capEndEdge] arguments decide whether to add a
  /// default margin and use rounded corners on the left and right side of the
  /// rectangular overlay, and they both default to true.
  const CupertinoPickerDefaultSelectionOverlay({
    super.key,
    this.background = CupertinoColors.tertiarySystemFill,
    this.capStartEdge = true,
    this.capEndEdge = true,
  });

  /// Whether to use the default use rounded corners and margin on the start side.
  final bool capStartEdge;

  /// Whether to use the default use rounded corners and margin on the end side.
  final bool capEndEdge;

  /// The color to fill in the background of the [CupertinoPickerDefaultSelectionOverlay].
  /// It Support for use [CupertinoDynamicColor].
  ///
  /// Typically this should not be set to a fully opaque color, as the currently
  /// selected item of the underlying [CupertinoPicker] should remain visible.
  /// Defaults to [CupertinoColors.tertiarySystemFill].
  final Color background;

  /// Default margin of the 'SelectionOverlay'.
  static const double _defaultSelectionOverlayHorizontalMargin = 9;

  /// Default radius of the 'SelectionOverlay'.
  static const double _defaultSelectionOverlayRadius = 8;

  @override
  Widget build(BuildContext context) {
    const radius = Radius.circular(_defaultSelectionOverlayRadius);

    return Container(
      margin: EdgeInsetsDirectional.only(
        start: capStartEdge ? _defaultSelectionOverlayHorizontalMargin : 0,
        end: capEndEdge ? _defaultSelectionOverlayHorizontalMargin : 0,
      ),
      decoration: ShapeDecoration(
        shape: RoundedSuperellipseBorder(
          borderRadius: BorderRadiusDirectional.horizontal(
            start: capStartEdge ? radius : Radius.zero,
            end: capEndEdge ? radius : Radius.zero,
          ),
        ),
        color: CupertinoDynamicColor.resolve(background, context),
      ),
    );
  }
}

// Turns the scroll semantics of the ListView into a single adjustable semantics
// node. This is done by removing all of the child semantics of the scroll
// wheel and using the scroll indexes to look up the current, previous, and
// next semantic label. This label is then turned into the value of a new
// adjustable semantic node, with adjustment callbacks wired to move the
// scroll controller.
class _CupertinoPickerSemantics extends SingleChildRenderObjectWidget {
  const _CupertinoPickerSemantics({super.child, required this.scrollController});

  final FixedExtentScrollController scrollController;

  @override
  RenderObject createRenderObject(BuildContext context) {
    assert(debugCheckHasDirectionality(context));
    return _RenderCupertinoPickerSemantics(scrollController, Directionality.of(context));
  }

  @override
  void updateRenderObject(
    BuildContext context,
    covariant _RenderCupertinoPickerSemantics renderObject,
  ) {
    assert(debugCheckHasDirectionality(context));
    renderObject
      ..textDirection = Directionality.of(context)
      ..controller = scrollController;
  }
}

class _RenderCupertinoPickerSemantics extends RenderProxyBox {
  _RenderCupertinoPickerSemantics(FixedExtentScrollController controller, this._textDirection) {
    _updateController(null, controller);
  }

  FixedExtentScrollController get controller => _controller;
  late FixedExtentScrollController _controller;
  set controller(FixedExtentScrollController value) => _updateController(_controller, value);

  // This method exists to allow controller to be non-null. It is only called with a null oldValue from constructor.
  void _updateController(FixedExtentScrollController? oldValue, FixedExtentScrollController value) {
    if (value == oldValue) {
      return;
    }
    if (oldValue != null) {
      oldValue.removeListener(_handleScrollUpdate);
    } else {
      _currentIndex = value.initialItem;
    }
    value.addListener(_handleScrollUpdate);
    _controller = value;
  }

  TextDirection get textDirection => _textDirection;
  TextDirection _textDirection;
  set textDirection(TextDirection value) {
    if (textDirection == value) {
      return;
    }
    _textDirection = value;
    markNeedsSemanticsUpdate();
  }

  int _currentIndex = 0;

  void _handleIncrease() {
    controller.jumpToItem(_currentIndex + 1);
  }

  void _handleDecrease() {
    controller.jumpToItem(_currentIndex - 1);
  }

  void _handleScrollUpdate() {
    if (controller.selectedItem == _currentIndex) {
      return;
    }
    _currentIndex = controller.selectedItem;
    markNeedsSemanticsUpdate();
  }

  @override
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    super.describeSemanticsConfiguration(config);
    config.isSemanticBoundary = true;
    config.textDirection = textDirection;
  }

  @override
  void assembleSemanticsNode(
    SemanticsNode node,
    SemanticsConfiguration config,
    Iterable<SemanticsNode> children,
  ) {
    if (children.isEmpty) {
      return super.assembleSemanticsNode(node, config, children);
    }
    final SemanticsNode scrollable = children.first;
    final indexedChildren = <int, SemanticsNode>{};
    scrollable.visitChildren((SemanticsNode child) {
      assert(child.indexInParent != null);
      indexedChildren[child.indexInParent!] = child;
      return true;
    });
    if (indexedChildren[_currentIndex] == null) {
      return node.updateWith(config: config);
    }
    final String currentLabel = indexedChildren[_currentIndex]!.label;
    // If the current item has an empty label (e.g., wrapped with ExcludeSemantics),
    // don't set any semantics configuration to avoid assertion errors.
    // The semantics system requires that if "value" is empty, "increasedValue"
    // and "decreasedValue" must also be empty, and no increase/decrease actions
    // should be set.
    if (currentLabel.isEmpty) {
      return node.updateWith(config: config);
    }
    config.value = currentLabel;
    final SemanticsNode? previousChild = indexedChildren[_currentIndex - 1];
    final SemanticsNode? nextChild = indexedChildren[_currentIndex + 1];
    // Only set increase/decrease actions if the adjacent item has a non-empty label.
    // Items wrapped with ExcludeSemantics will have empty labels and should not
    // be navigable via accessibility actions.
    if (nextChild != null && nextChild.label.isNotEmpty) {
      config.increasedValue = nextChild.label;
      config.onIncrease = _handleIncrease;
    }
    if (previousChild != null && previousChild.label.isNotEmpty) {
      config.decreasedValue = previousChild.label;
      config.onDecrease = _handleDecrease;
    }
    node.updateWith(config: config);
  }

  @override
  void dispose() {
    super.dispose();
    controller.removeListener(_handleScrollUpdate);
  }
}

class _CupertinoPickerListWheelChildDelegateWrapper implements ListWheelChildDelegate {
  _CupertinoPickerListWheelChildDelegateWrapper(this._wrapped, {required this.onTappedChild});
  final ListWheelChildDelegate _wrapped;
  final void Function(int index) onTappedChild;

  @override
  Widget? build(BuildContext context, int index) {
    final Widget? child = _wrapped.build(context, index);
    if (child == null) {
      return child;
    }
    return GestureDetector(
      behavior: HitTestBehavior.translucent,
      excludeFromSemantics: true,
      onTap: () => onTappedChild(index),
      child: child,
    );
  }

  @override
  int? get estimatedChildCount => _wrapped.estimatedChildCount;

  @override
  bool shouldRebuild(covariant _CupertinoPickerListWheelChildDelegateWrapper oldDelegate) =>
      _wrapped.shouldRebuild(oldDelegate._wrapped);

  @override
  int trueIndexOf(int index) => _wrapped.trueIndexOf(index);
}
