// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:collection';
import 'dart:math' as math show pi;
import 'dart:ui' as ui;

import 'package:flutter/foundation.dart' show Brightness, clampDouble;
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';

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

// The radius of the toolbar RRect shape.
// Value extracted from https://developer.apple.com/design/resources/.
const Radius _kToolbarBorderRadius = Radius.circular(8.0);

// Vertical distance between the tip of the arrow and the line of text the arrow
// is pointing to. The value used here is eyeballed.
const double _kToolbarContentDistance = 8.0;

// The size of the arrow pointing to the anchor. Eyeballed value.
const Size _kToolbarArrowSize = Size(14.0, 7.0);

// Minimal padding from tip of the selection toolbar arrow to horizontal edges of the
// screen. Eyeballed value.
const double _kArrowScreenPadding = 26.0;

// The size and thickness of the chevron icon used for navigating between toolbar pages.
// Eyeballed values.
const double _kToolbarChevronSize = 10.0;
const double _kToolbarChevronThickness = 2.0;

// Color was measured from a screenshot of iOS 16.0.2
// TODO(LongCatIsLooong): https://github.com/flutter/flutter/issues/41507.
const CupertinoDynamicColor _kToolbarBackgroundColor = CupertinoDynamicColor.withBrightness(
  color: Color(0xFFF6F6F6),
  darkColor: Color(0xFF222222),
);

// Color was measured from a screenshot of iOS 16.0.2.
const CupertinoDynamicColor _kToolbarDividerColor = CupertinoDynamicColor.withBrightness(
  color: Color(0xFFD6D6D6),
  darkColor: Color(0xFF424242),
);

const CupertinoDynamicColor _kToolbarTextColor = CupertinoDynamicColor.withBrightness(
  color: CupertinoColors.black,
  darkColor: CupertinoColors.white,
);

const Duration _kToolbarTransitionDuration = Duration(milliseconds: 125);

/// The type for a Function that builds a toolbar's container with the given
/// child.
///
/// The anchor is provided in global coordinates.
///
/// See also:
///
///   * [CupertinoTextSelectionToolbar.toolbarBuilder], which is of this type.
///   * [TextSelectionToolbar.toolbarBuilder], which is similar, but for an
///     Material-style toolbar.
typedef CupertinoToolbarBuilder = Widget Function(
  BuildContext context,
  Offset anchorAbove,
  Offset anchorBelow,
  Widget child,
);

/// An iOS-style text selection toolbar.
///
/// Typically displays buttons for text manipulation, e.g. copying and pasting
/// text.
///
/// Tries to position itself above [anchorAbove], but if it doesn't fit, then
/// it positions itself below [anchorBelow].
///
/// If any children don't fit in the menu, an overflow menu will automatically
/// be created.
///
/// See also:
///
///  * [AdaptiveTextSelectionToolbar], which builds the toolbar for the current
///    platform.
///  * [TextSelectionToolbar], which is similar, but builds an Android-style
///    toolbar.
class CupertinoTextSelectionToolbar extends StatelessWidget {
  /// Creates an instance of CupertinoTextSelectionToolbar.
  const CupertinoTextSelectionToolbar({
    super.key,
    required this.anchorAbove,
    required this.anchorBelow,
    required this.children,
    this.toolbarBuilder = _defaultToolbarBuilder,
  }) : assert(children.length > 0);

  /// {@macro flutter.material.TextSelectionToolbar.anchorAbove}
  final Offset anchorAbove;

  /// {@macro flutter.material.TextSelectionToolbar.anchorBelow}
  final Offset anchorBelow;

  /// {@macro flutter.material.TextSelectionToolbar.children}
  ///
  /// See also:
  ///   * [CupertinoTextSelectionToolbarButton], which builds a default
  ///     Cupertino-style text selection toolbar text button.
  final List<Widget> children;

  /// {@macro flutter.material.TextSelectionToolbar.toolbarBuilder}
  ///
  /// The given anchor and isAbove can be used to position an arrow, as in the
  /// default Cupertino toolbar.
  final CupertinoToolbarBuilder toolbarBuilder;

  /// Minimal padding from all edges of the selection toolbar to all edges of the
  /// viewport.
  ///
  /// See also:
  ///
  ///  * [SpellCheckSuggestionsToolbar], which uses this same value for its
  ///    padding from the edges of the viewport.
  ///  * [TextSelectionToolbar], which uses this same value as well.
  static const double kToolbarScreenPadding = 8.0;

  // Builds a toolbar just like the default iOS toolbar, with the right color
  // background and a rounded cutout with an arrow.
  static Widget _defaultToolbarBuilder(
    BuildContext context,
    Offset anchorAbove,
    Offset anchorBelow,
    Widget child,
  ) {
    return _CupertinoTextSelectionToolbarShape(
      anchorAbove: anchorAbove,
      anchorBelow: anchorBelow,
      shadowColor: CupertinoTheme.brightnessOf(context) == Brightness.light
          ? CupertinoColors.black.withOpacity(0.2)
          : null,
      child: ColoredBox(
        color: _kToolbarBackgroundColor.resolveFrom(context),
        child: child,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    assert(debugCheckHasMediaQuery(context));
    final EdgeInsets mediaQueryPadding = MediaQuery.paddingOf(context);

    final double paddingAbove = mediaQueryPadding.top + kToolbarScreenPadding;

    // The arrow, which points to the anchor, has some margin so it can't get
    // too close to the horizontal edges of the screen.
    final double leftMargin = _kArrowScreenPadding + mediaQueryPadding.left;
    final double rightMargin = MediaQuery.sizeOf(context).width - mediaQueryPadding.right - _kArrowScreenPadding;

    final Offset anchorAboveAdjusted = Offset(
      clampDouble(anchorAbove.dx, leftMargin, rightMargin),
      anchorAbove.dy - _kToolbarContentDistance - paddingAbove,
    );
    final Offset anchorBelowAdjusted = Offset(
      clampDouble(anchorBelow.dx, leftMargin, rightMargin),
      anchorBelow.dy + _kToolbarContentDistance - paddingAbove,
    );

    return Padding(
      padding: EdgeInsets.fromLTRB(
        kToolbarScreenPadding,
        paddingAbove,
        kToolbarScreenPadding,
        kToolbarScreenPadding,
      ),
      child: CustomSingleChildLayout(
        delegate: TextSelectionToolbarLayoutDelegate(
          anchorAbove: anchorAboveAdjusted,
          anchorBelow: anchorBelowAdjusted,
        ),
        child: _CupertinoTextSelectionToolbarContent(
          anchorAbove: anchorAboveAdjusted,
          anchorBelow: anchorBelowAdjusted,
          toolbarBuilder: toolbarBuilder,
          children: children,
        ),
      ),
    );
  }
}

// Clips the child so that it has the shape of the default iOS text selection
// toolbar, with rounded corners and an arrow pointing at the anchor.
//
// The anchor should be in global coordinates.
class _CupertinoTextSelectionToolbarShape extends SingleChildRenderObjectWidget {
  const _CupertinoTextSelectionToolbarShape({
    required Offset anchorAbove,
    required Offset anchorBelow,
    Color? shadowColor,
    super.child,
  }) : _anchorAbove = anchorAbove,
       _anchorBelow = anchorBelow,
       _shadowColor = shadowColor;

  final Offset _anchorAbove;
  final Offset _anchorBelow;
  final Color? _shadowColor;

  @override
  _RenderCupertinoTextSelectionToolbarShape createRenderObject(BuildContext context) => _RenderCupertinoTextSelectionToolbarShape(
    _anchorAbove,
    _anchorBelow,
    _shadowColor,
    null,
  );

  @override
  void updateRenderObject(BuildContext context, _RenderCupertinoTextSelectionToolbarShape renderObject) {
    renderObject
      ..anchorAbove = _anchorAbove
      ..anchorBelow = _anchorBelow
      ..shadowColor = _shadowColor;
  }
}

// Clips the child into the shape of the default iOS text selection toolbar.
//
// The shape is a rounded rectangle with a protruding arrow pointing at the
// given anchor in the direction indicated by isAbove.
//
// In order to allow the child to render itself independent of isAbove, its
// height is clipped on both the top and the bottom, leaving the arrow remaining
// on the necessary side.
class _RenderCupertinoTextSelectionToolbarShape extends RenderShiftedBox {
  _RenderCupertinoTextSelectionToolbarShape(
    this._anchorAbove,
    this._anchorBelow,
    this._shadowColor,
    super.child,
  );

  @override
  bool get isRepaintBoundary => true;

  Offset get anchorAbove => _anchorAbove;
  Offset _anchorAbove;
  set anchorAbove(Offset value) {
    if (value == _anchorAbove) {
      return;
    }
    _anchorAbove = value;
    markNeedsLayout();
  }

  Offset get anchorBelow => _anchorBelow;
  Offset _anchorBelow;
  set anchorBelow(Offset value) {
    if (value == _anchorBelow) {
      return;
    }
    _anchorBelow = value;
    markNeedsLayout();
  }

  Color? get shadowColor => _shadowColor;
  Color? _shadowColor;
  set shadowColor(Color? value) {
    if (value == _shadowColor) {
      return;
    }
    _shadowColor = value;
    markNeedsPaint();
  }

  bool _isAbove(double childHeight) => anchorAbove.dy >= childHeight - _kToolbarArrowSize.height * 2;

  BoxConstraints _constraintsForChild(BoxConstraints constraints) {
    return BoxConstraints(
      minWidth: _kToolbarArrowSize.width + _kToolbarBorderRadius.x * 2,
    ).enforce(constraints.loosen());
  }

  Offset _computeChildOffset(Size childSize) {
    return Offset(0.0, _isAbove(childSize.height) ? -_kToolbarArrowSize.height : 0.0);
  }

  @override
  double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
    final RenderBox? child = this.child;
    if (child == null) {
      return null;
    }
    final BoxConstraints enforcedConstraint = _constraintsForChild(constraints);
    final double? result = child.getDryBaseline(enforcedConstraint, baseline);
    return result == null
      ? null
      : result + _computeChildOffset(child.getDryLayout(enforcedConstraint)).dy;
  }

  @override
  void performLayout() {
    final RenderBox? child = this.child;
    if (child == null) {
      return;
    }

    child.layout(_constraintsForChild(constraints), parentUsesSize: true);
    // The buttons are padded on both top and bottom sufficiently to have
    // the arrow clipped out of it on either side. By
    // using this approach, the buttons don't need any special padding that
    // depends on isAbove.
    // The height of one arrow will be clipped off of the child, so adjust the
    // size and position to remove that piece from the layout.
    final BoxParentData childParentData = child.parentData! as BoxParentData;
    childParentData.offset = _computeChildOffset(child.size);
    size = Size(
      child.size.width,
      child.size.height - _kToolbarArrowSize.height,
    );
  }

  // Returns the RRect inside which the child is painted.
  RRect _shapeRRect(RenderBox child) {
    final Rect rect = Offset(0.0, _kToolbarArrowSize.height)
        & Size(child.size.width, child.size.height - _kToolbarArrowSize.height * 2);
    return RRect.fromRectAndRadius(rect, _kToolbarBorderRadius).scaleRadii();
  }

  // Adds the given `rrect` to the current `path`, starting from the last point
  // in `path` and ends after the last corner of the rrect (closest corner to
  // `startAngle` in the counterclockwise direction), without closing the path.
  //
  // The `startAngle` argument must be a multiple of pi / 2, with 0 being the
  // positive half of the x-axis, and pi / 2 being the negative half of the
  // y-axis.
  //
  // For instance, if `startAngle` equals pi/2 then this method draws a line
  // segment to the bottom-left corner of `rrect` from the last point in `path`,
  // and follows the `rrect` path clockwise until the bottom-right corner is
  // added, then this method returns the mutated path without closing it.
  static Path _addRRectToPath(Path path, RRect rrect, { required double startAngle }) {
    const double halfPI = math.pi / 2;
    assert(startAngle % halfPI == 0.0);
    final Rect rect = rrect.outerRect;

    final List<(Offset, Radius)> rrectCorners = <(Offset, Radius)>[
      (rect.bottomRight, -rrect.brRadius),
      (rect.bottomLeft, Radius.elliptical(rrect.blRadiusX, -rrect.blRadiusY)),
      (rect.topLeft, rrect.tlRadius),
      (rect.topRight, Radius.elliptical(-rrect.trRadiusX, rrect.trRadiusY)),
    ];

    // Add the 4 corners to the path clockwise. Convert radians to quadrants
    // to avoid fp arithmetics. The order is br -> bl -> tl -> tr if the starting
    // angle is 0.
    final int startQuadrantIndex = startAngle ~/ halfPI;
    for (int i = startQuadrantIndex; i < rrectCorners.length + startQuadrantIndex; i += 1) {
      final (Offset vertex, Radius rectCenterOffset) = rrectCorners[i % rrectCorners.length];
      final Offset otherVertex = Offset(vertex.dx + 2 * rectCenterOffset.x, vertex.dy + 2 * rectCenterOffset.y);
      final Rect rect = Rect.fromPoints(vertex, otherVertex);
      path.arcTo(rect, halfPI * i, halfPI, false);
    }
    return path;
  }

  // The path is described in the toolbar child's coordinate system.
  Path _clipPath(RenderBox child, RRect rrect) {
    final Path path = Path();
    // If there isn't enough width for the arrow + radii, ignore the arrow.
    // Because of the constraints we gave children in performLayout, this should
    // only happen if the parent isn't wide enough which should be very rare, and
    // when that happens the arrow won't be too useful anyways.
    if (_kToolbarBorderRadius.x * 2 + _kToolbarArrowSize.width > size.width) {
      return path..addRRect(rrect);
    }

    final bool isAbove = _isAbove(child.size.height);
    final Offset localAnchor = globalToLocal(isAbove ? _anchorAbove : _anchorBelow);
    final double arrowTipX = clampDouble(
      localAnchor.dx,
      _kToolbarBorderRadius.x + _kToolbarArrowSize.width / 2,
      size.width - _kToolbarArrowSize.width / 2 - _kToolbarBorderRadius.x,
    );

    // Draw the path clockwise, starting from the beginning side of the arrow.
    if (isAbove) {
      final double arrowBaseY = child.size.height - _kToolbarArrowSize.height;
      final double arrowTipY = child.size.height;
      path
        ..moveTo(arrowTipX + _kToolbarArrowSize.width / 2, arrowBaseY)  // right side of the arrow triangle
        ..lineTo(arrowTipX, arrowTipY)                                  // The tip of the arrow
        ..lineTo(arrowTipX - _kToolbarArrowSize.width / 2, arrowBaseY); // left side of the arrow triangle
    } else {
      final double arrowBaseY = _kToolbarArrowSize.height;
      const double arrowTipY = 0.0;
      path
        ..moveTo(arrowTipX - _kToolbarArrowSize.width / 2, arrowBaseY)  // right side of the arrow triangle
        ..lineTo(arrowTipX, arrowTipY)                                  // The tip of the arrow
        ..lineTo(arrowTipX + _kToolbarArrowSize.width / 2, arrowBaseY); // left side of the arrow triangle
    }
    final double startAngle = isAbove ? math.pi / 2 : -math.pi / 2;
    return _addRRectToPath(path, rrect, startAngle: startAngle)..close();
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    final RenderBox? child = this.child;
    if (child == null) {
      return;
    }

    final BoxParentData childParentData = child.parentData! as BoxParentData;

    final RRect rrect = _shapeRRect(child);
    final Path clipPath = _clipPath(child, rrect);

    // If configured, paint the shadow beneath the shape.
    if (_shadowColor != null) {
      final BoxShadow boxShadow = BoxShadow(
        color: _shadowColor!,
        blurRadius: 15.0,
      );
      final RRect shadowRRect = RRect.fromLTRBR(
        rrect.left,
        rrect.top,
        rrect.right,
        rrect.bottom + _kToolbarArrowSize.height,
        _kToolbarBorderRadius,
      ).shift(offset + childParentData.offset + boxShadow.offset);
      context.canvas.drawRRect(shadowRRect, boxShadow.toPaint());
    }

    _clipPathLayer.layer = context.pushClipPath(
      needsCompositing,
      offset + childParentData.offset,
      Offset.zero & child.size,
      clipPath,
      (PaintingContext innerContext, Offset innerOffset) => innerContext.paintChild(child, innerOffset),
      oldLayer: _clipPathLayer.layer,
    );
  }

  final LayerHandle<ClipPathLayer> _clipPathLayer = LayerHandle<ClipPathLayer>();
  Paint? _debugPaint;

  @override
  void dispose() {
    _clipPathLayer.layer = null;
    super.dispose();
  }

  @override
  void debugPaintSize(PaintingContext context, Offset offset) {
    assert(() {
      final RenderBox? child = this.child;
      if (child == null) {
        return true;
      }

      final ui.Paint debugPaint = _debugPaint ??= Paint()
        ..shader = ui.Gradient.linear(
          Offset.zero,
          const Offset(10.0, 10.0),
          const <Color>[Color(0x00000000), Color(0xFFFF00FF), Color(0xFFFF00FF), Color(0x00000000)],
          const <double>[0.25, 0.25, 0.75, 0.75],
          TileMode.repeated,
        )
        ..strokeWidth = 2.0
        ..style = PaintingStyle.stroke;

      final BoxParentData childParentData = child.parentData! as BoxParentData;
      final Path clipPath = _clipPath(child, _shapeRRect(child));
      context.canvas.drawPath(clipPath.shift(offset + childParentData.offset), debugPaint);
      return true;
    }());
  }

  @override
  bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
    final RenderBox? child = this.child;
    if (child == null) {
      return false;
    }

    // Positions outside of the clipped area of the child are not counted as
    // hits.
    final BoxParentData childParentData = child.parentData! as BoxParentData;
    final Rect hitBox = Rect.fromLTWH(
      childParentData.offset.dx,
      childParentData.offset.dy + _kToolbarArrowSize.height,
      child.size.width,
      child.size.height - _kToolbarArrowSize.height * 2,
    );
    if (!hitBox.contains(position)) {
      return false;
    }

    return super.hitTestChildren(result, position: position);
  }
}

// A toolbar containing the given children. If they overflow the width
// available, then the menu will be paginated with the overflowing children
// displayed on subsequent pages.
//
// The anchor should be in global coordinates.
class _CupertinoTextSelectionToolbarContent extends StatefulWidget {
  const _CupertinoTextSelectionToolbarContent({
    required this.anchorAbove,
    required this.anchorBelow,
    required this.toolbarBuilder,
    required this.children,
  }) : assert(children.length > 0);

  final Offset anchorAbove;
  final Offset anchorBelow;
  final List<Widget> children;
  final CupertinoToolbarBuilder toolbarBuilder;

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

class _CupertinoTextSelectionToolbarContentState extends State<_CupertinoTextSelectionToolbarContent> with TickerProviderStateMixin {
  // Controls the fading of the buttons within the menu during page transitions.
  late AnimationController _controller;
  int? _nextPage;
  int _page = 0;

  final GlobalKey _toolbarItemsKey = GlobalKey();

  void _onHorizontalDragEnd(DragEndDetails details) {
    final double? velocity = details.primaryVelocity;

    if (velocity != null && velocity != 0) {
      if (velocity > 0) {
        _handlePreviousPage();
      } else {
        _handleNextPage();
      }
    }
  }

  void _handleNextPage() {
    final RenderBox? renderToolbar =
      _toolbarItemsKey.currentContext?.findRenderObject() as RenderBox?;

    if (renderToolbar is _RenderCupertinoTextSelectionToolbarItems && renderToolbar.hasNextPage) {
      _controller.reverse();
      _controller.addStatusListener(_statusListener);
      _nextPage = _page + 1;
    }
  }

  void _handlePreviousPage() {
    final RenderBox? renderToolbar =
      _toolbarItemsKey.currentContext?.findRenderObject() as RenderBox?;

    if (renderToolbar is _RenderCupertinoTextSelectionToolbarItems && renderToolbar.hasPreviousPage) {
      _controller.reverse();
      _controller.addStatusListener(_statusListener);
      _nextPage = _page - 1;
    }
  }

  void _statusListener(AnimationStatus status) {
    if (status != AnimationStatus.dismissed) {
      return;
    }

    setState(() {
      _page = _nextPage!;
      _nextPage = null;
    });
    _controller.forward();
    _controller.removeStatusListener(_statusListener);
  }

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      value: 1.0,
      vsync: this,
      // This was eyeballed on a physical iOS device running iOS 13.
      duration: _kToolbarTransitionDuration,
    );
  }

  @override
  void didUpdateWidget(_CupertinoTextSelectionToolbarContent oldWidget) {
    super.didUpdateWidget(oldWidget);
    // If the children are changing, the current page should be reset.
    if (widget.children != oldWidget.children) {
      _page = 0;
      _nextPage = null;
      _controller.forward();
      _controller.removeStatusListener(_statusListener);
    }
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final Color chevronColor = _kToolbarTextColor.resolveFrom(context);

    // Wrap the children and the chevron painters in Center with widthFactor
    // and heightFactor of 1.0 so _CupertinoTextSelectionToolbarItems can get
    // the natural size of the buttons and then expand vertically as needed.
    final Widget backButton = Center(
      widthFactor: 1.0,
      heightFactor: 1.0,
      child: CupertinoTextSelectionToolbarButton(
        onPressed: _handlePreviousPage,
        child: IgnorePointer(
          child: CustomPaint(
            painter: _LeftCupertinoChevronPainter(color: chevronColor),
            size: const Size.square(_kToolbarChevronSize),
          ),
        ),
      ),
    );
    final Widget nextButton = Center(
      widthFactor: 1.0,
      heightFactor: 1.0,
      child: CupertinoTextSelectionToolbarButton(
        onPressed: _handleNextPage,
        child: IgnorePointer(
          child: CustomPaint(
            painter: _RightCupertinoChevronPainter(color: chevronColor),
            size: const Size.square(_kToolbarChevronSize),
          ),
        ),
      ),
    );
    final List<Widget> children = widget.children.map((Widget child) {
      return Center(
        widthFactor: 1.0,
        heightFactor: 1.0,
        child: child,
      );
    }).toList();

    return widget.toolbarBuilder(context, widget.anchorAbove, widget.anchorBelow, FadeTransition(
      opacity: _controller,
      child: AnimatedSize(
        duration: _kToolbarTransitionDuration,
        curve: Curves.decelerate,
        child: GestureDetector(
          onHorizontalDragEnd: _onHorizontalDragEnd,
          child: _CupertinoTextSelectionToolbarItems(
            key: _toolbarItemsKey,
            page: _page,
            backButton: backButton,
            dividerColor: _kToolbarDividerColor.resolveFrom(context),
            dividerWidth: 1.0 / MediaQuery.devicePixelRatioOf(context),
            nextButton: nextButton,
            children: children,
          ),
        ),
      ),
    ));
  }
}

// These classes help to test the chevrons. As _CupertinoChevronPainter must be
// private, it's possible to check the runtimeType of each chevron to know if
// they should be pointing left or right.
class _LeftCupertinoChevronPainter extends _CupertinoChevronPainter {
  _LeftCupertinoChevronPainter({required super.color}) : super(isLeft: true);
}
class _RightCupertinoChevronPainter extends _CupertinoChevronPainter {
  _RightCupertinoChevronPainter({required super.color}) : super(isLeft: false);
}
abstract class _CupertinoChevronPainter extends CustomPainter {
  _CupertinoChevronPainter({
    required this.color,
    required this.isLeft,
  });

  final Color color;

  /// If this is true the chevron will point left, else it will point right.
  final bool isLeft;

  @override
  void paint(Canvas canvas, Size size) {
    assert(size.height == size.width, 'size must have the same height and width: $size');

    final double iconSize = size.height;

    // The chevron is half of a square rotated 45˚, so it needs a margin of 1/4
    // its size on each side to be centered horizontally.
    //
    // If pointing left, it means the left half of a square is being used and
    // the offset is positive. If pointing right, the right half is being used
    // and the offset is negative.
    final Offset centerOffset = Offset(
      iconSize / 4 * (isLeft ? 1 : -1),
      0,
    );

    final Offset firstPoint = Offset(iconSize / 2, 0) + centerOffset;
    final Offset middlePoint = Offset(isLeft ? 0 : iconSize, iconSize / 2) + centerOffset;
    final Offset lowerPoint = Offset(iconSize / 2, iconSize) + centerOffset;

    final Paint paint = Paint()
      ..color = color
      ..style = PaintingStyle.stroke
      ..strokeWidth = _kToolbarChevronThickness
      ..strokeCap = StrokeCap.round
      ..strokeJoin = StrokeJoin.round;

    // `drawLine` is used here because it's testable. When using `drawPath`,
    // there's no way to test that the chevron points to the correct side.
    canvas.drawLine(firstPoint, middlePoint, paint);
    canvas.drawLine(middlePoint, lowerPoint, paint);
  }

  @override
  bool shouldRepaint(_CupertinoChevronPainter oldDelegate) =>
    oldDelegate.color != color || oldDelegate.isLeft != isLeft;
}

// The custom RenderObjectWidget that, together with
// _RenderCupertinoTextSelectionToolbarItems and
// _CupertinoTextSelectionToolbarItemsElement, paginates the menu items.
class _CupertinoTextSelectionToolbarItems extends RenderObjectWidget {
  _CupertinoTextSelectionToolbarItems({
    super.key,
    required this.page,
    required this.children,
    required this.backButton,
    required this.dividerColor,
    required this.dividerWidth,
    required this.nextButton,
  }) : assert(children.isNotEmpty);

  final Widget backButton;
  final List<Widget> children;
  final Color dividerColor;
  final double dividerWidth;
  final Widget nextButton;
  final int page;

  @override
  _RenderCupertinoTextSelectionToolbarItems createRenderObject(BuildContext context) {
    return _RenderCupertinoTextSelectionToolbarItems(
      dividerColor: dividerColor,
      dividerWidth: dividerWidth,
      page: page,
    );
  }

  @override
  void updateRenderObject(BuildContext context, _RenderCupertinoTextSelectionToolbarItems renderObject) {
    renderObject
      ..page = page
      ..dividerColor = dividerColor
      ..dividerWidth = dividerWidth;
  }

  @override
  _CupertinoTextSelectionToolbarItemsElement createElement() => _CupertinoTextSelectionToolbarItemsElement(this);
}

// The custom RenderObjectElement that helps paginate the menu items.
class _CupertinoTextSelectionToolbarItemsElement extends RenderObjectElement {
  _CupertinoTextSelectionToolbarItemsElement(
    _CupertinoTextSelectionToolbarItems super.widget,
  );

  late List<Element> _children;
  final Map<_CupertinoTextSelectionToolbarItemsSlot, Element> slotToChild = <_CupertinoTextSelectionToolbarItemsSlot, Element>{};

  // We keep a set of forgotten children to avoid O(n^2) work walking _children
  // repeatedly to remove children.
  final Set<Element> _forgottenChildren = HashSet<Element>();

  @override
  _RenderCupertinoTextSelectionToolbarItems get renderObject => super.renderObject as _RenderCupertinoTextSelectionToolbarItems;

  void _updateRenderObject(RenderBox? child, _CupertinoTextSelectionToolbarItemsSlot slot) {
    switch (slot) {
      case _CupertinoTextSelectionToolbarItemsSlot.backButton:
        renderObject.backButton = child;
      case _CupertinoTextSelectionToolbarItemsSlot.nextButton:
        renderObject.nextButton = child;
    }
  }

  @override
  void insertRenderObjectChild(RenderObject child, Object? slot) {
    if (slot is _CupertinoTextSelectionToolbarItemsSlot) {
      assert(child is RenderBox);
      _updateRenderObject(child as RenderBox, slot);
      assert(renderObject.slottedChildren.containsKey(slot));
      return;
    }
    if (slot is IndexedSlot) {
      assert(renderObject.debugValidateChild(child));
      renderObject.insert(child as RenderBox, after: slot.value?.renderObject as RenderBox?);
      return;
    }
    assert(false, 'slot must be _CupertinoTextSelectionToolbarItemsSlot or IndexedSlot');
  }

  // This is not reachable for children that don't have an IndexedSlot.
  @override
  void moveRenderObjectChild(RenderObject child, IndexedSlot<Element> oldSlot, IndexedSlot<Element> newSlot) {
    assert(child.parent == renderObject);
    renderObject.move(child as RenderBox, after: newSlot.value.renderObject as RenderBox?);
  }

  static bool _shouldPaint(Element child) {
    return (child.renderObject!.parentData! as ToolbarItemsParentData).shouldPaint;
  }

  @override
  void removeRenderObjectChild(RenderObject child, Object? slot) {
    // Check if the child is in a slot.
    if (slot is _CupertinoTextSelectionToolbarItemsSlot) {
      assert(child is RenderBox);
      assert(renderObject.slottedChildren.containsKey(slot));
      _updateRenderObject(null, slot);
      assert(!renderObject.slottedChildren.containsKey(slot));
      return;
    }

    // Otherwise look for it in the list of children.
    assert(slot is IndexedSlot);
    assert(child.parent == renderObject);
    renderObject.remove(child as RenderBox);
  }

  @override
  void visitChildren(ElementVisitor visitor) {
    slotToChild.values.forEach(visitor);
    for (final Element child in _children) {
      if (!_forgottenChildren.contains(child)) {
        visitor(child);
      }
    }
  }

  @override
  void forgetChild(Element child) {
    assert(slotToChild.containsValue(child) || _children.contains(child));
    assert(!_forgottenChildren.contains(child));
    // Handle forgetting a child in children or in a slot.
    if (slotToChild.containsKey(child.slot)) {
      final _CupertinoTextSelectionToolbarItemsSlot slot = child.slot! as _CupertinoTextSelectionToolbarItemsSlot;
      slotToChild.remove(slot);
    } else {
      _forgottenChildren.add(child);
    }
    super.forgetChild(child);
  }

  // Mount or update slotted child.
  void _mountChild(Widget widget, _CupertinoTextSelectionToolbarItemsSlot slot) {
    final Element? oldChild = slotToChild[slot];
    final Element? newChild = updateChild(oldChild, widget, slot);
    if (oldChild != null) {
      slotToChild.remove(slot);
    }
    if (newChild != null) {
      slotToChild[slot] = newChild;
    }
  }

  @override
  void mount(Element? parent, Object? newSlot) {
    super.mount(parent, newSlot);
    // Mount slotted children.
    final _CupertinoTextSelectionToolbarItems toolbarItems = widget as _CupertinoTextSelectionToolbarItems;
    _mountChild(toolbarItems.backButton, _CupertinoTextSelectionToolbarItemsSlot.backButton);
    _mountChild(toolbarItems.nextButton, _CupertinoTextSelectionToolbarItemsSlot.nextButton);

    // Mount list children.
    Element? previousChild;
    _children = List<Element>.generate(toolbarItems.children.length, (int i) {
      final Element result = inflateWidget(toolbarItems.children[i], IndexedSlot<Element?>(i, previousChild));
      previousChild = result;
      return result;
    }, growable: false);
  }

  @override
  void debugVisitOnstageChildren(ElementVisitor visitor) {
    // Visit slot children.
    for (final Element child in slotToChild.values) {
      if (_shouldPaint(child) && !_forgottenChildren.contains(child)) {
        visitor(child);
      }
    }
    // Visit list children.
    _children
        .where((Element child) => !_forgottenChildren.contains(child) && _shouldPaint(child))
        .forEach(visitor);
  }

  @override
  void update(_CupertinoTextSelectionToolbarItems newWidget) {
    super.update(newWidget);
    assert(widget == newWidget);

    // Update slotted children.
    final _CupertinoTextSelectionToolbarItems toolbarItems = widget as _CupertinoTextSelectionToolbarItems;
    _mountChild(toolbarItems.backButton, _CupertinoTextSelectionToolbarItemsSlot.backButton);
    _mountChild(toolbarItems.nextButton, _CupertinoTextSelectionToolbarItemsSlot.nextButton);

    // Update list children.
    _children = updateChildren(_children, toolbarItems.children, forgottenChildren: _forgottenChildren);
    _forgottenChildren.clear();
  }
}

// The custom RenderBox that helps paginate the menu items.
class _RenderCupertinoTextSelectionToolbarItems extends RenderBox with ContainerRenderObjectMixin<RenderBox, ToolbarItemsParentData>, RenderBoxContainerDefaultsMixin<RenderBox, ToolbarItemsParentData> {
  _RenderCupertinoTextSelectionToolbarItems({
    required Color dividerColor,
    required double dividerWidth,
    required int page,
  }) : _dividerColor = dividerColor,
       _dividerWidth = dividerWidth,
       _page = page,
       super();

  final Map<_CupertinoTextSelectionToolbarItemsSlot, RenderBox> slottedChildren = <_CupertinoTextSelectionToolbarItemsSlot, RenderBox>{};

  late bool hasNextPage;
  late bool hasPreviousPage;

  RenderBox? _updateChild(RenderBox? oldChild, RenderBox? newChild, _CupertinoTextSelectionToolbarItemsSlot slot) {
    if (oldChild != null) {
      dropChild(oldChild);
      slottedChildren.remove(slot);
    }
    if (newChild != null) {
      slottedChildren[slot] = newChild;
      adoptChild(newChild);
    }
    return newChild;
  }

  int _page;
  int get page => _page;
  set page(int value) {
    if (value == _page) {
      return;
    }
    _page = value;
    markNeedsLayout();
  }

  Color _dividerColor;
  Color get dividerColor => _dividerColor;
  set dividerColor(Color value) {
    if (value == _dividerColor) {
      return;
    }
    _dividerColor = value;
    markNeedsLayout();
  }

  double _dividerWidth;
  double get dividerWidth => _dividerWidth;
  set dividerWidth(double value) {
    if (value == _dividerWidth) {
      return;
    }
    _dividerWidth = value;
    markNeedsLayout();
  }

  RenderBox? _backButton;
  RenderBox? get backButton => _backButton;
  set backButton(RenderBox? value) {
    _backButton = _updateChild(_backButton, value, _CupertinoTextSelectionToolbarItemsSlot.backButton);
  }

  RenderBox? _nextButton;
  RenderBox? get nextButton => _nextButton;
  set nextButton(RenderBox? value) {
    _nextButton = _updateChild(_nextButton, value, _CupertinoTextSelectionToolbarItemsSlot.nextButton);
  }

  @override
  void performLayout() {
    if (firstChild == null) {
      size = constraints.smallest;
      return;
    }

    // First pass: determine the height of the tallest child.
    double greatestHeight = 0.0;
    visitChildren((RenderObject renderObjectChild) {
      final RenderBox child = renderObjectChild as RenderBox;
      final double childHeight = child.getMaxIntrinsicHeight(constraints.maxWidth);
      if (childHeight > greatestHeight) {
        greatestHeight = childHeight;
      }
    });

    // Layout slotted children.
    final BoxConstraints slottedConstraints = BoxConstraints(
      maxWidth: constraints.maxWidth,
      minHeight: greatestHeight,
      maxHeight: greatestHeight,
    );
    _backButton!.layout(slottedConstraints, parentUsesSize: true);
    _nextButton!.layout(slottedConstraints, parentUsesSize: true);

    final double subsequentPageButtonsWidth = _backButton!.size.width + _nextButton!.size.width;
    double currentButtonPosition = 0.0;
    late double toolbarWidth; // The width of the whole widget.
    int currentPage = 0;
    int i = -1;
    visitChildren((RenderObject renderObjectChild) {
      i++;
      final RenderBox child = renderObjectChild as RenderBox;
      final ToolbarItemsParentData childParentData = child.parentData! as ToolbarItemsParentData;
      childParentData.shouldPaint = false;

      // Skip slotted children and children on pages after the visible page.
      if (child == _backButton || child == _nextButton || currentPage > _page) {
        return;
      }

      // If this is the last child on the first page, it's ok to fit without a forward button.
      // Note childCount doesn't include slotted children which come before the list ones.
      double paginationButtonsWidth = currentPage == 0
          ? i == childCount + 1 ? 0.0 : _nextButton!.size.width
          : subsequentPageButtonsWidth;

      // The width of the menu is set by the first page.
      child.layout(
        BoxConstraints(
          maxWidth: constraints.maxWidth - paginationButtonsWidth,
          minHeight: greatestHeight,
          maxHeight: greatestHeight,
        ),
        parentUsesSize: true,
      );

      // If this child causes the current page to overflow, move to the next
      // page and relayout the child.
      final double currentWidth = currentButtonPosition + paginationButtonsWidth + child.size.width;
      if (currentWidth > constraints.maxWidth) {
        currentPage++;
        currentButtonPosition = _backButton!.size.width + dividerWidth;
        paginationButtonsWidth = _backButton!.size.width + _nextButton!.size.width;
        child.layout(
          BoxConstraints(
            maxWidth: constraints.maxWidth - paginationButtonsWidth,
            minHeight: greatestHeight,
            maxHeight: greatestHeight,
          ),
          parentUsesSize: true,
        );
      }
      childParentData.offset = Offset(currentButtonPosition, 0.0);
      currentButtonPosition += child.size.width + dividerWidth;
      childParentData.shouldPaint = currentPage == page;

      if (currentPage == page) {
        toolbarWidth = currentButtonPosition;
      }
    });

    // It shouldn't be possible to navigate beyond the last page.
    assert(page <= currentPage);

    // Position page nav buttons.
    if (currentPage > 0) {
      final ToolbarItemsParentData nextButtonParentData = _nextButton!.parentData! as ToolbarItemsParentData;
      final ToolbarItemsParentData backButtonParentData = _backButton!.parentData! as ToolbarItemsParentData;
      // The forward button only shows when there's a page after this one.
      if (page != currentPage) {
        nextButtonParentData.offset = Offset(toolbarWidth, 0.0);
        nextButtonParentData.shouldPaint = true;
        toolbarWidth += nextButton!.size.width;
      }
      if (page > 0) {
        backButtonParentData.offset = Offset.zero;
        backButtonParentData.shouldPaint = true;
        // No need to add the width of the back button to toolbarWidth here. It's
        // already been taken care of when laying out the children to
        // accommodate the back button.
      }
    } else {
      // No divider for the next button when there's only one page.
      toolbarWidth -= dividerWidth;
    }

    // Update previous/next page values so that we can check in the horizontal
    // drag gesture callback if it's possible to navigate.
    hasNextPage = page != currentPage;
    hasPreviousPage = page > 0;

    size = constraints.constrain(Size(toolbarWidth, greatestHeight));
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    visitChildren((RenderObject renderObjectChild) {
      final RenderBox child = renderObjectChild as RenderBox;
      final ToolbarItemsParentData childParentData = child.parentData! as ToolbarItemsParentData;

      if (childParentData.shouldPaint) {
        final Offset childOffset = childParentData.offset + offset;
        context.paintChild(child, childOffset);

        // backButton is a slotted child and is not in the children list, so its
        // childParentData.nextSibling is null. So either when there's a
        // nextSibling or when child is the backButton, draw a divider to the
        // child's right.
        if (childParentData.nextSibling != null || child == backButton) {
          context.canvas.drawLine(
            Offset(child.size.width, 0) + childOffset,
            Offset(child.size.width, child.size.height) + childOffset,
            Paint()..color = dividerColor,
          );
        }
      }
    });
  }

  @override
  void setupParentData(RenderBox child) {
    if (child.parentData is! ToolbarItemsParentData) {
      child.parentData = ToolbarItemsParentData();
    }
  }

  // Returns true if the single child is hit by the given position.
  static bool hitTestChild(RenderBox? child, BoxHitTestResult result, { required Offset position }) {
    if (child == null) {
      return false;
    }
    final ToolbarItemsParentData childParentData = child.parentData! as ToolbarItemsParentData;
    if (!childParentData.shouldPaint) {
      return false;
    }
    return result.addWithPaintOffset(
      offset: childParentData.offset,
      position: position,
      hitTest: (BoxHitTestResult result, Offset transformed) {
        assert(transformed == position - childParentData.offset);
        return child.hitTest(result, position: transformed);
      },
    );
  }

  @override
  bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
    // Hit test list children.
    RenderBox? child = lastChild;
    while (child != null) {
      final ToolbarItemsParentData childParentData = child.parentData! as ToolbarItemsParentData;

      // Don't hit test children that aren't shown.
      if (!childParentData.shouldPaint) {
        child = childParentData.previousSibling;
        continue;
      }

      if (hitTestChild(child, result, position: position)) {
        return true;
      }
      child = childParentData.previousSibling;
    }

    // Hit test slot children.
    if (hitTestChild(backButton, result, position: position)) {
      return true;
    }
    if (hitTestChild(nextButton, result, position: position)) {
      return true;
    }

    return false;
  }

  @override
  void attach(PipelineOwner owner) {
    // Attach list children.
    super.attach(owner);

    // Attach slot children.
    for (final RenderBox child in slottedChildren.values) {
      child.attach(owner);
    }
  }

  @override
  void detach() {
    // Detach list children.
    super.detach();

    // Detach slot children.
    for (final RenderBox child in slottedChildren.values) {
      child.detach();
    }
  }

  @override
  void redepthChildren() {
    visitChildren((RenderObject renderObjectChild) {
      final RenderBox child = renderObjectChild as RenderBox;
      redepthChild(child);
    });
  }

  @override
  void visitChildren(RenderObjectVisitor visitor) {
    // Visit the slotted children.
    if (_backButton != null) {
      visitor(_backButton!);
    }
    if (_nextButton != null) {
      visitor(_nextButton!);
    }
    // Visit the list children.
    super.visitChildren(visitor);
  }

  // Visit only the children that should be painted.
  @override
  void visitChildrenForSemantics(RenderObjectVisitor visitor) {
    visitChildren((RenderObject renderObjectChild) {
      final RenderBox child = renderObjectChild as RenderBox;
      final ToolbarItemsParentData childParentData = child.parentData! as ToolbarItemsParentData;
      if (childParentData.shouldPaint) {
        visitor(renderObjectChild);
      }
    });
  }

  @override
  List<DiagnosticsNode> debugDescribeChildren() {
    final List<DiagnosticsNode> value = <DiagnosticsNode>[];
    visitChildren((RenderObject renderObjectChild) {
      final RenderBox child = renderObjectChild as RenderBox;
      if (child == backButton) {
        value.add(child.toDiagnosticsNode(name: 'back button'));
      } else if (child == nextButton) {
        value.add(child.toDiagnosticsNode(name: 'next button'));

      // List children.
      } else {
        value.add(child.toDiagnosticsNode(name: 'menu item'));
      }
    });
    return value;
  }
}

// The slots that can be occupied by widgets in
// _CupertinoTextSelectionToolbarItems, excluding the list of children.
enum _CupertinoTextSelectionToolbarItemsSlot {
  backButton,
  nextButton,
}
