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

// This file is run as part of a reduced test set in CI on Mac and Windows
// machines.
@Tags(<String>['reduced-test-set'])

import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

import '../rendering/mock_canvas.dart';
import '../rendering/rendering_tester.dart';

void main() {
  testWidgets('ListWheelScrollView respects clipBehavior', (WidgetTester tester) async {
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ListWheelScrollView(
          itemExtent: 2000.0, // huge extent to trigger clip
          children: <Widget>[Container()],
        ),
      ),
    );

    // 1st, check that the render object has received the default clip behavior.
    final RenderListWheelViewport renderObject = tester.allRenderObjects.whereType<RenderListWheelViewport>().first;
    expect(renderObject.clipBehavior, equals(Clip.hardEdge));

    // 2nd, check that the painting context has received the default clip behavior.
    final TestClipPaintingContext context = TestClipPaintingContext();
    renderObject.paint(context, Offset.zero);
    expect(context.clipBehavior, equals(Clip.hardEdge));

    // 3rd, pump a new widget to check that the render object can update its clip behavior.
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ListWheelScrollView(
          itemExtent: 2000.0, // huge extent to trigger clip
          clipBehavior: Clip.antiAlias,
          children: <Widget>[Container()],
        ),
      ),
    );
    expect(renderObject.clipBehavior, equals(Clip.antiAlias));

    // 4th, check that a non-default clip behavior can be sent to the painting context.
    renderObject.paint(context, Offset.zero);
    expect(context.clipBehavior, equals(Clip.antiAlias));
  });

  group('construction check', () {
    testWidgets('ListWheelScrollView needs positive diameter ratio', (WidgetTester tester) async {
      expect(
        () => ListWheelScrollView(
          diameterRatio: nonconst(-2.0),
          itemExtent: 20.0,
          children: const <Widget>[],
        ),
        throwsA(isAssertionError.having(
          (AssertionError error) => error.message,
          'message',
          contains("You can't set a diameterRatio of 0"),
        )),
      );
    });

    testWidgets('ListWheelScrollView can have zero child', (WidgetTester tester) async {
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            itemExtent: 50.0,
            children: const <Widget>[],
          ),
        ),
      );
      expect(tester.getSize(find.byType(ListWheelScrollView)), const Size(800.0, 600.0));
    });

    testWidgets('ListWheelScrollView needs positive magnification', (WidgetTester tester) async {
      expect(
        () {
          ListWheelScrollView(
            useMagnifier: true,
            magnification: -1.0,
            itemExtent: 20.0,
            children: <Widget>[Container()],
          );
        },
        throwsAssertionError,
      );
    });

    testWidgets('ListWheelScrollView needs valid overAndUnderCenterOpacity', (WidgetTester tester) async {
      expect(
        () {
          ListWheelScrollView(
            overAndUnderCenterOpacity: -1,
            itemExtent: 20.0,
            children: <Widget>[Container()],
          );
        },
        throwsAssertionError,
      );

      expect(
        () {
          ListWheelScrollView(
            overAndUnderCenterOpacity: 2,
            itemExtent: 20.0,
            children: <Widget>[Container()],
          );
        },
        throwsAssertionError,
      );

      expect(
        () {
          ListWheelScrollView(
            itemExtent: 20.0,
            children: <Widget>[Container()],
          );
        },
        isNot(throwsAssertionError),
      );

      expect(
        () {
          ListWheelScrollView(
            overAndUnderCenterOpacity: 0,
            itemExtent: 20.0,
            children: <Widget>[Container()],
          );
        },
        isNot(throwsAssertionError),
      );
    });
  });

  group('infinite scrolling', () {
    testWidgets('infinite looping list', (WidgetTester tester) async {
      final FixedExtentScrollController controller =
        FixedExtentScrollController();

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView.useDelegate(
            controller: controller,
            itemExtent: 100.0,
            onSelectedItemChanged: (_) { },
            childDelegate: ListWheelChildLoopingListDelegate(
              children: List<Widget>.generate(10, (int index) {
                return SizedBox(
                  width: 400.0,
                  height: 100.0,
                  child: Text(index.toString()),
                );
              }),
            ),
          ),
        ),
      );

      // The first item is at the center of the viewport.
      expect(
      tester.getTopLeft(find.widgetWithText(SizedBox, '0')),
      const Offset(0.0, 250.0),
      );

      // The last item is just before the first item.
      expect(
        tester.getTopLeft(find.widgetWithText(SizedBox, '9')),
        const Offset(0.0, 150.0),
      );

      controller.jumpTo(1000.0);
      await tester.pump();

      // We have passed the end of the list, the list should have looped back.
      expect(
        tester.getTopLeft(find.widgetWithText(SizedBox, '0')),
        const Offset(0.0, 250.0),
      );
    });

    testWidgets('infinite child builder', (WidgetTester tester) async {
      final FixedExtentScrollController controller =
        FixedExtentScrollController();

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView.useDelegate(
            controller: controller,
            itemExtent: 100.0,
            onSelectedItemChanged: (_) { },
            childDelegate: ListWheelChildBuilderDelegate(
              builder: (BuildContext context, int index) {
                return SizedBox(
                  width: 400.0,
                  height: 100.0,
                  child: Text(index.toString()),
                );
              },
            ),
          ),
        ),
      );

      // Can be scrolled infinitely for negative indexes.
      controller.jumpTo(-100000.0);
      await tester.pump();
      expect(
        tester.getTopLeft(find.widgetWithText(SizedBox, '-1000')),
        const Offset(0.0, 250.0),
      );

      // Can be scrolled infinitely for positive indexes.
      controller.jumpTo(100000.0);
      await tester.pump();
      expect(
        tester.getTopLeft(find.widgetWithText(SizedBox, '1000')),
        const Offset(0.0, 250.0),
      );
    });

    testWidgets('child builder with lower and upper limits', (WidgetTester tester) async {
      final List<int> paintedChildren = <int>[];

      final FixedExtentScrollController controller =
        FixedExtentScrollController(initialItem: -10);

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView.useDelegate(
            controller: controller,
            itemExtent: 100.0,
            onSelectedItemChanged: (_) { },
            childDelegate: ListWheelChildBuilderDelegate(
              builder: (BuildContext context, int index) {
                if (index < -15 || index > -5)
                  return null;
                return SizedBox(
                  width: 400.0,
                  height: 100.0,
                  child: CustomPaint(
                    painter: TestCallbackPainter(onPaint: () {
                      paintedChildren.add(index);
                    }),
                  ),
                );
              },
            ),
          ),
        ),
      );

      expect(paintedChildren, <int>[-13, -12, -11, -10, -9, -8, -7]);

      // Flings with high velocity and stop at the lower limit.
      paintedChildren.clear();
      await tester.fling(
        find.byType(ListWheelScrollView),
        const Offset(0.0, 1000.0),
        1000.0,
      );
      await tester.pumpAndSettle();
      expect(controller.selectedItem, -15);

      // Flings with high velocity and stop at the upper limit.
      await tester.fling(
        find.byType(ListWheelScrollView),
        const Offset(0.0, -1000.0),
        1000.0,
      );
      await tester.pumpAndSettle();
      expect(controller.selectedItem, -5);
    });
  });

  group('layout', () {
    // Regression test for https://github.com/flutter/flutter/issues/58144
    testWidgets('ListWheelScrollView childDelegate update test', (WidgetTester tester) async {
      final FixedExtentScrollController controller = FixedExtentScrollController();
      Widget buildFrame(int childCount) {
        return Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView.useDelegate(
            controller: controller,
            itemExtent: 100.0,
            onSelectedItemChanged: (_) { },
            childDelegate: ListWheelChildBuilderDelegate(
              childCount: childCount,
              builder: (BuildContext context, int index) {
                return SizedBox(
                  width: 400.0,
                  height: 100.0,
                  child: Text(index.toString()),
                );
              },
            ),
          ),
        );
      }

      await tester.pumpWidget(buildFrame(1));
      expect(tester.renderObject(find.text('0')).attached, true);

      await tester.pumpWidget(buildFrame(2));
      expect(tester.renderObject(find.text('0')).attached, true);
      expect(tester.renderObject(find.text('1')).attached, true);
    });

    testWidgets("ListWheelScrollView takes parent's size with small children", (WidgetTester tester) async {
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            // Inner children smaller than the outer window.
            itemExtent: 50.0,
            children: <Widget>[
              Container(
                height: 50.0,
                color: const Color(0xFFFFFFFF),
              ),
            ],
          ),
        ),
      );
      expect(tester.getTopLeft(find.byType(ListWheelScrollView)), Offset.zero);
      // Standard test screen size.
      expect(tester.getBottomRight(find.byType(ListWheelScrollView)), const Offset(800.0, 600.0));
    });

    testWidgets("ListWheelScrollView takes parent's size with large children", (WidgetTester tester) async {
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            // Inner children 5000.0px.
            itemExtent: 50.0,
            children: List<Widget>.generate(100, (int index) {
              return Container(
                height: 50.0,
                color: const Color(0xFFFFFFFF),
              );
            }),
          ),
        ),
      );
      expect(tester.getTopLeft(find.byType(ListWheelScrollView)), Offset.zero);
      // Still fills standard test screen size.
      expect(tester.getBottomRight(find.byType(ListWheelScrollView)), const Offset(800.0, 600.0));
    });

    testWidgets("ListWheelScrollView children can't be bigger than itemExtent", (WidgetTester tester) async {
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            itemExtent: 50.0,
            children: const <Widget>[
              SizedBox(
                height: 200.0,
                width: 200.0,
                child: Center(
                  child: Text('blah'),
                ),
              ),
            ],
          ),
        ),
      );
      expect(tester.getSize(find.byType(SizedBox)), const Size(200.0, 50.0));
      expect(find.text('blah'), findsOneWidget);
    });

    testWidgets('builder is never called twice for same index', (WidgetTester tester) async {
      final Set<int> builtChildren = <int>{};
      final FixedExtentScrollController controller =
        FixedExtentScrollController();

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView.useDelegate(
            controller: controller,
            itemExtent: 100.0,
            onSelectedItemChanged: (_) { },
            childDelegate: ListWheelChildBuilderDelegate(
              builder: (BuildContext context, int index) {
                expect(builtChildren.contains(index), false);
                builtChildren.add(index);

                return SizedBox(
                  width: 400.0,
                  height: 100.0,
                  child: Text(index.toString()),
                );
              },
            ),
          ),
        ),
      );

      // Scrolls up and down to check if builder is called twice.
      controller.jumpTo(-10000.0);
      await tester.pump();
      controller.jumpTo(10000.0);
      await tester.pump();
      controller.jumpTo(-10000.0);
      await tester.pump();
    });

    testWidgets('only visible children are maintained as children of the rendered viewport', (WidgetTester tester) async {
      final FixedExtentScrollController controller =
        FixedExtentScrollController();

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            itemExtent: 100.0,
            onSelectedItemChanged: (_) { },
            children: List<Widget>.generate(16, (int index) {
              return Text(index.toString());
            }),
          ),
        ),
      );

      final RenderListWheelViewport viewport = tester.renderObject(find.byType(ListWheelViewport)) as RenderListWheelViewport;

      // Item 0 is in the middle. There are 3 children visible after it, so the
      // value of childCount should be 4.
      expect(viewport.childCount, 4);

      controller.jumpToItem(8);
      await tester.pump();
      // Item 8 is in the middle. There are 3 children visible before it and 3
      // after it, so the value of childCount should be 7.
      expect(viewport.childCount, 7);

      controller.jumpToItem(15);
      await tester.pump();
      // Item 15 is in the middle. There are 3 children visible before it, so the
      // value of childCount should be 4.
      expect(viewport.childCount, 4);
    });

    testWidgets('a tighter squeeze lays out more children', (WidgetTester tester) async {
      final FixedExtentScrollController controller =
        FixedExtentScrollController(initialItem: 10);

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            itemExtent: 100.0,
            onSelectedItemChanged: (_) { },
            children: List<Widget>.generate(20, (int index) {
              return Text(index.toString());
            }),
          ),
        ),
      );

      final RenderListWheelViewport viewport = tester.renderObject(find.byType(ListWheelViewport)) as RenderListWheelViewport;

      // The screen is vertically 600px. Since the middle item is centered,
      // half of the first and last items are visible, making 7 children visible.
      expect(viewport.childCount, 7);

      // Pump the same widget again but with double the squeeze.
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            itemExtent: 100.0,
            squeeze: 2,
            onSelectedItemChanged: (_) { },
            children: List<Widget>.generate(20, (int index) {
              return Text(index.toString());
            }),
          ),
        ),
      );

      // 12 instead of 6 children are laid out + 1 because the middle item is
      // centered.
      expect(viewport.childCount, 13);
    });
  });

  group('pre-transform viewport', () {
    testWidgets('ListWheelScrollView starts and ends from the middle', (WidgetTester tester) async {
      final ScrollController controller = ScrollController();
      final List<int> paintedChildren = <int>[];

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            itemExtent: 100.0,
            children: List<Widget>.generate(100, (int index) {
              return CustomPaint(
                painter: TestCallbackPainter(onPaint: () {
                  paintedChildren.add(index);
                }),
              );
            }),
          ),
        ),
      );

      // Screen is 600px tall and the first item starts at 250px. The first 4
      // children are visible.
      expect(paintedChildren, <int>[0, 1, 2, 3]);

      controller.jumpTo(1000.0);
      paintedChildren.clear();

      await tester.pump();
      // Item number 10 is now in the middle of the screen at 250px. 9, 8, 7 are
      // visible before it and 11, 12, 13 are visible after it.
      expect(paintedChildren, <int>[7, 8, 9, 10, 11, 12, 13]);

      // Move to the last item.
      controller.jumpTo(9900.0);
      paintedChildren.clear();

      await tester.pump();
      // Item 99 is in the middle at 250px.
      expect(paintedChildren, <int>[96, 97, 98, 99]);
    });

    testWidgets('A child gets painted as soon as its first pixel is in the viewport', (WidgetTester tester) async {
      final ScrollController controller = ScrollController(initialScrollOffset: 50.0);
      final List<int> paintedChildren = <int>[];

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            itemExtent: 100.0,
            children: List<Widget>.generate(10, (int index) {
              return CustomPaint(
                painter: TestCallbackPainter(onPaint: () {
                  paintedChildren.add(index);
                }),
              );
            }),
          ),
        ),
      );

      // Screen is 600px tall and the first item starts at 200px. The first 4
      // children are visible.
      expect(paintedChildren, <int>[0, 1, 2, 3]);

      paintedChildren.clear();
      // Move down by 1px.
      await tester.drag(find.byType(ListWheelScrollView), const Offset(0.0, -1.0));
      await tester.pump();

      // Now the first pixel of item 5 enters the viewport.
      expect(paintedChildren, <int>[0, 1, 2, 3, 4]);
    });

    testWidgets('A child is no longer painted after its last pixel leaves the viewport', (WidgetTester tester) async {
      final ScrollController controller = ScrollController(initialScrollOffset: 250.0);
      final List<int> paintedChildren = <int>[];

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            itemExtent: 100.0,
            children: List<Widget>.generate(10, (int index) {
              return CustomPaint(
                painter: TestCallbackPainter(onPaint: () {
                  paintedChildren.add(index);
                }),
              );
            }),
          ),
        ),
      );

      // The first item is at 0px and the 600px screen is full in the
      // **untransformed plane's viewport painting coordinates**
      expect(paintedChildren, <int>[0, 1, 2, 3, 4, 5]);

      paintedChildren.clear();
      // Go down another 99px.
      controller.jumpTo(349.0);
      await tester.pump();

      // One more item now visible with the last pixel of 0 showing.
      expect(paintedChildren, <int>[0, 1, 2, 3, 4, 5, 6]);

      paintedChildren.clear();
      // Go down one more pixel.
      controller.jumpTo(350.0);
      await tester.pump();

      // Item 0 no longer visible.
      expect(paintedChildren, <int>[1, 2, 3, 4, 5, 6]);
    });
  });

  group('viewport transformation', () {
    testWidgets('Center child is magnified', (WidgetTester tester) async {
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: RepaintBoundary(
            key: const Key('list_wheel_scroll_view'),
            child: ListWheelScrollView(
              useMagnifier: true,
              magnification: 2.0,
              itemExtent: 50.0,
              children: List<Widget>.generate(10, (int index) {
                return const Placeholder();
              }),
            ),
          ),
        ),
      );

      await expectLater(
        find.byKey(const Key('list_wheel_scroll_view')),
        matchesGoldenFile('list_wheel_scroll_view.center_child.magnified.png'),
      );
    });

    testWidgets('Default middle transform', (WidgetTester tester) async {
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            itemExtent: 100.0,
            children: const <Widget>[
              SizedBox(
                width: 200.0,
                child: Center(
                  child: Text('blah'),
                ),
              ),
            ],
          ),
        ),
      );

      final RenderListWheelViewport viewport = tester.renderObject(find.byType(ListWheelViewport)) as RenderListWheelViewport;
      expect(viewport, paints..transform(
        matrix4: equals(<dynamic>[
          1.0, 0.0, 0.0, 0.0,
          0.0, 1.0, 0.0, 0.0,
          -1.2 /* origin centering multiplied */, -0.9/* origin centering multiplied*/, 1.0, -0.003 /* inverse of perspective */,
          moreOrLessEquals(0.0), moreOrLessEquals(0.0), 0.0, moreOrLessEquals(1.0),
        ]),
      ));
    });

    testWidgets('Curve the wheel to the left', (WidgetTester tester) async {
      final ScrollController controller = ScrollController(initialScrollOffset: 300.0);
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: RepaintBoundary(
            key: const Key('list_wheel_scroll_view'),
            child: ListWheelScrollView(
              controller: controller,
              offAxisFraction: 0.5,
              itemExtent: 50.0,
              children: List<Widget>.generate(32, (int index) {
                return const Placeholder();
              }),
          ),
        ),
      ),
      );

      await expectLater(
        find.byKey(const Key('list_wheel_scroll_view')),
        matchesGoldenFile('list_wheel_scroll_view.curved_wheel.left.png'),
      );
    });

    testWidgets('Scrolling, diameterRatio, perspective all changes matrix', (WidgetTester tester) async {
      final ScrollController controller = ScrollController(initialScrollOffset: 200.0);

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            itemExtent: 100.0,
            children: const <Widget>[
              SizedBox(
                width: 200.0,
                child: Center(
                  child: Text('blah'),
                ),
              ),
            ],
          ),
        ),
      );

      final RenderListWheelViewport viewport = tester.renderObject(find.byType(ListWheelViewport)) as RenderListWheelViewport;
      expect(viewport, paints..transform(
        matrix4: equals(<dynamic>[
          1.0, 0.0, 0.0, 0.0,
          moreOrLessEquals(-0.41042417199080244), moreOrLessEquals(0.6318744917928065), moreOrLessEquals(0.3420201433256687), moreOrLessEquals(-0.0010260604299770061),
          moreOrLessEquals(-1.12763114494309), moreOrLessEquals(-1.1877435020329863), moreOrLessEquals(0.9396926207859084), moreOrLessEquals(-0.0028190778623577253),
          moreOrLessEquals(166.54856463138663), moreOrLessEquals(-62.20844875763376), moreOrLessEquals(-138.79047052615562), moreOrLessEquals(1.4163714115784667),
        ]),
      ));

      // Increase diameter.
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            diameterRatio: 3.0,
            itemExtent: 100.0,
            children: const <Widget>[
              SizedBox(
                width: 200.0,
                child: Center(
                  child: Text('blah'),
                ),
              ),
            ],
          ),
        ),
      );

      expect(viewport, paints..transform(
        matrix4: equals(<dynamic>[
          1.0, 0.0, 0.0, 0.0,
          moreOrLessEquals(-0.26954971336161726), moreOrLessEquals(0.7722830529455648), moreOrLessEquals(0.22462476113468105), moreOrLessEquals(-0.0006738742834040432),
          moreOrLessEquals(-1.1693344055601331), moreOrLessEquals(-1.101625565304781), moreOrLessEquals(0.9744453379667777), moreOrLessEquals(-0.002923336013900333),
          moreOrLessEquals(108.46394900436536), moreOrLessEquals(-113.14792465797223), moreOrLessEquals(-90.38662417030434), moreOrLessEquals(1.2711598725109134),
        ]),
      ));

      // Decrease perspective.
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            perspective: 0.0001,
            itemExtent: 100.0,
            children: const <Widget>[
              SizedBox(
                width: 200.0,
                child: Center(
                  child: Text('blah'),
                ),
              ),
            ],
          ),
        ),
      );

      expect(viewport, paints..transform(
        matrix4: equals(<dynamic>[
          1.0, 0.0, 0.0, 0.0,
          moreOrLessEquals(-0.01368080573302675), moreOrLessEquals(0.9294320164861384), moreOrLessEquals(0.3420201433256687), moreOrLessEquals(-0.000034202014332566874),
          moreOrLessEquals(-0.03758770483143634), moreOrLessEquals(-0.370210921949246), moreOrLessEquals(0.9396926207859084), moreOrLessEquals(-0.00009396926207859085),
          moreOrLessEquals(5.551618821046304), moreOrLessEquals(-182.95615811538906), moreOrLessEquals(-138.79047052615562), moreOrLessEquals(1.0138790470526158),
        ]),
      ));

      // Scroll a bit.
      controller.jumpTo(300.0);
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            itemExtent: 100.0,
            children: const <Widget>[
              SizedBox(
                width: 200.0,
                child: Center(
                  child: Text('blah'),
                ),
              ),
            ],
          ),
        ),
      );

      expect(viewport, paints..transform(
        matrix4: equals(<dynamic>[
          1.0, 0.0, 0.0, 0.0,
          -0.6, moreOrLessEquals(0.41602540378443875), moreOrLessEquals(0.5), moreOrLessEquals(-0.0015),
          moreOrLessEquals(-1.0392304845413265), moreOrLessEquals(-1.2794228634059948), moreOrLessEquals(0.8660254037844387), moreOrLessEquals(-0.0025980762113533163),
          moreOrLessEquals(276.46170927520404), moreOrLessEquals(-52.46133917892857), moreOrLessEquals(-230.38475772933677), moreOrLessEquals(1.69115427318801),
        ]),
      ));
    });

    testWidgets('offAxisFraction, magnification changes matrix', (WidgetTester tester) async {
      final ScrollController controller = ScrollController(initialScrollOffset: 200.0);

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            itemExtent: 100.0,
            offAxisFraction: 0.5,
            children: const <Widget>[
              SizedBox(
                width: 200.0,
                child: Center(
                  child: Text('blah'),
                ),
              ),
            ],
          ),
        ),
      );

      final RenderListWheelViewport viewport = tester.renderObject(find.byType(ListWheelViewport)) as RenderListWheelViewport;
      expect(
        viewport,
        paints
          ..transform(
            matrix4: equals(<dynamic>[
              1.0,
              0.0,
              0.0,
              0.0,
              0.0,
              moreOrLessEquals(0.6318744917928063),
              moreOrLessEquals(0.3420201433256688),
              moreOrLessEquals(-0.0010260604299770066),
              0.0,
              moreOrLessEquals(-1.1877435020329863),
              moreOrLessEquals(0.9396926207859083),
              moreOrLessEquals(-0.002819077862357725),
              0.0,
              moreOrLessEquals(-62.20844875763376),
              moreOrLessEquals(-138.79047052615562),
              moreOrLessEquals(1.4163714115784667),
            ]),
          ),
      );

      controller.jumpTo(0.0);

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            itemExtent: 100.0,
            offAxisFraction: 0.5,
            useMagnifier: true,
            magnification: 1.5,
            children: const <Widget>[
              SizedBox(
                width: 200.0,
                child: Center(
                  child: Text('blah'),
                ),
              ),
            ],
          ),
        ),
      );

      expect(
        viewport,
        paints
          ..transform(
            matrix4: equals(<dynamic>[
              1.5,
              0.0,
              0.0,
              0.0,
              0.0,
              1.5,
              0.0,
              0.0,
              0.0,
              0.0,
              1.5,
              0.0,
              0.0,
              -150.0,
              0.0,
              1.0,
            ]),
          ),
      );
    });
  });

  group('scroll notifications', () {
    testWidgets('no onSelectedItemChanged callback on first build', (WidgetTester tester) async {
      bool itemChangeCalled = false;
      void onItemChange(int _) { itemChangeCalled = true; }

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            itemExtent: 100.0,
            onSelectedItemChanged: onItemChange,
            children: const <Widget>[
              SizedBox(
                width: 200.0,
                child: Center(
                  child: Text('blah'),
                ),
              ),
            ],
          ),
        ),
      );

      expect(itemChangeCalled, false);
    });

    testWidgets('onSelectedItemChanged when a new item is closest to center', (WidgetTester tester) async {
      final List<int> selectedItems = <int>[];

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            itemExtent: 100.0,
            onSelectedItemChanged: (int index) { selectedItems.add(index); },
            children: List<Widget>.generate(10, (int index) {
              return const Placeholder();
            }),
          ),
        ),
      );

      final TestGesture scrollGesture = await tester.startGesture(const Offset(10.0, 10.0));
      // Item 0 is still closest to the center. No updates.
      await scrollGesture.moveBy(const Offset(0.0, -49.0));
      expect(selectedItems.isEmpty, true);

      // Now item 1 is closest to the center.
      await scrollGesture.moveBy(const Offset(0.0, -1.0));
      expect(selectedItems, <int>[1]);

      // Now item 1 is still closest to the center for another full itemExtent (100px).
      await scrollGesture.moveBy(const Offset(0.0, -99.0));
      expect(selectedItems, <int>[1]);

      await scrollGesture.moveBy(const Offset(0.0, -1.0));
      expect(selectedItems, <int>[1, 2]);

      // Going back triggers previous item indices.
      await scrollGesture.moveBy(const Offset(0.0, 50.0));
      expect(selectedItems, <int>[1, 2, 1]);
    });

    testWidgets('onSelectedItemChanged reports only in valid range', (WidgetTester tester) async {
      final List<int> selectedItems = <int>[];

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            itemExtent: 100.0,
            onSelectedItemChanged: (int index) { selectedItems.add(index); },
            // So item 0 is at 0 and item 9 is at 900 in the scrollable range.
            children: List<Widget>.generate(10, (int index) {
              return const Placeholder();
            }),
          ),
        ),
      );

      final TestGesture scrollGesture = await tester.startGesture(const Offset(10.0, 10.0));

      // First move back past the beginning.
      await scrollGesture.moveBy(const Offset(0.0, 70.0));

      for (double verticalOffset = 0.0; verticalOffset > -2000.0; verticalOffset -= 10.0) {
        // Then gradually move down by a total vertical extent much higher than
        // the scrollable extent.
        await scrollGesture.moveTo(Offset(0.0, verticalOffset));
      }

      // The list should only cover the list of valid items. Item 0 would not
      // be included because the current item never left the 0 index until it
      // went to 1.
      expect(selectedItems, <int>[1, 2, 3, 4, 5, 6, 7, 8, 9]);
    });
  });

  group('scroll controller', () {
    testWidgets('initialItem', (WidgetTester tester) async {
      final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 10);
      final List<int> paintedChildren = <int>[];

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            itemExtent: 100.0,
            children: List<Widget>.generate(100, (int index) {
              return CustomPaint(
                painter: TestCallbackPainter(onPaint: () {
                  paintedChildren.add(index);
                }),
              );
            }),
          ),
        ),
      );

      // Screen is 600px tall. Item 10 is in the center and each item is 100px tall.
      expect(paintedChildren, <int>[7, 8, 9, 10, 11, 12, 13]);
      expect(controller.selectedItem, 10);
    });

    testWidgets('controller jump', (WidgetTester tester) async {
      final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 10);
      final List<int> paintedChildren = <int>[];

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            itemExtent: 100.0,
            children: List<Widget>.generate(100, (int index) {
              return CustomPaint(
                painter: TestCallbackPainter(onPaint: () {
                  paintedChildren.add(index);
                }),
              );
            }),
          ),
        ),
      );

      // Screen is 600px tall. Item 10 is in the center and each item is 100px tall.
      expect(paintedChildren, <int>[7, 8, 9, 10, 11, 12, 13]);

      paintedChildren.clear();
      controller.jumpToItem(0);
      await tester.pump();

      expect(paintedChildren, <int>[0, 1, 2, 3]);
      expect(controller.selectedItem, 0);
    });

    testWidgets('controller animateToItem', (WidgetTester tester) async {
      final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 10);
      final List<int> paintedChildren = <int>[];

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            itemExtent: 100.0,
            children: List<Widget>.generate(100, (int index) {
              return CustomPaint(
                painter: TestCallbackPainter(onPaint: () {
                  paintedChildren.add(index);
                }),
              );
            }),
          ),
        ),
      );

      // Screen is 600px tall. Item 10 is in the center and each item is 100px tall.
      expect(paintedChildren, <int>[7, 8, 9, 10, 11, 12, 13]);

      paintedChildren.clear();
      controller.animateToItem(
        0,
        duration: const Duration(seconds: 1),
        curve: Curves.linear,
      );
      await tester.pump();
      await tester.pump(const Duration(seconds: 1));

      expect(paintedChildren, <int>[0, 1, 2, 3]);
      expect(controller.selectedItem, 0);
    });

    testWidgets('onSelectedItemChanged and controller are in sync', (WidgetTester tester) async {
      final List<int> selectedItems = <int>[];
      final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 10);

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: controller,
            itemExtent: 100.0,
            onSelectedItemChanged: (int index) { selectedItems.add(index); },
            children: List<Widget>.generate(100, (int index) {
              return const Placeholder();
            }),
          ),
        ),
      );

      final TestGesture scrollGesture = await tester.startGesture(const Offset(10.0, 10.0));
      await scrollGesture.moveBy(const Offset(0.0, -49.0));
      await tester.pump();
      expect(selectedItems.isEmpty, true);
      expect(controller.selectedItem, 10);

      await scrollGesture.moveBy(const Offset(0.0, -1.0));
      await tester.pump();
      expect(selectedItems, <int>[11]);
      expect(controller.selectedItem, 11);

      await scrollGesture.moveBy(const Offset(0.0, 70.0));
      await tester.pump();
      expect(selectedItems, <int>[11, 10]);
      expect(controller.selectedItem, 10);
    });

    testWidgets('controller hot swappable', (WidgetTester tester) async {
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            itemExtent: 100.0,
            children: List<Widget>.generate(100, (int index) {
              return const Placeholder();
            }),
          ),
        ),
      );

      // Item 5 is now selected.
      await tester.drag(find.byType(ListWheelScrollView), const Offset(0.0, -500.0));
      await tester.pump();

      final FixedExtentScrollController newController =
          FixedExtentScrollController(initialItem: 30);

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            controller: newController,
            itemExtent: 100.0,
            children: List<Widget>.generate(100, (int index) {
              return const Placeholder();
            }),
          ),
        ),
      );

      // initialItem doesn't do anything since the scroll position was already
      // created.
      expect(newController.selectedItem, 5);

      newController.jumpToItem(50);
      expect(newController.selectedItem, 50);
      expect(newController.position.pixels, 5000.0);

      // Now remove the controller
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: ListWheelScrollView(
            itemExtent: 100.0,
            children: List<Widget>.generate(100, (int index) {
              return const Placeholder();
            }),
          ),
        ),
      );

      // Internally, that same controller is still attached and still at the
      // same place.
      expect(newController.selectedItem, 50);
    });
  });

  group('physics', () {
    testWidgets('fling velocities too low snaps back to the same item', (WidgetTester tester) async {
      final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 40);
      final List<double> scrolledPositions = <double>[];

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: NotificationListener<ScrollNotification>(
            onNotification: (ScrollNotification notification) {
              if (notification is ScrollUpdateNotification)
                scrolledPositions.add(notification.metrics.pixels);
              return false;
            },
            child: ListWheelScrollView(
              controller: controller,
              physics: const FixedExtentScrollPhysics(),
              itemExtent: 1000.0,
              children: List<Widget>.generate(100, (int index) {
                return const Placeholder();
              }),
            ),
          ),
        ),
      );

      await tester.fling(
        find.byType(ListWheelScrollView),
        const Offset(0.0, -50.0),
        800.0,
      );

      // At this moment, the ballistics is started but 50px is still inside the
      // initial item.
      expect(controller.selectedItem, 40);
      // A tester.fling creates and pumps 50 pointer events.
      expect(scrolledPositions.length, 50);
      expect(scrolledPositions.last, moreOrLessEquals(40 * 1000.0 + 50.0, epsilon: 0.2));

      // Let the spring back simulation finish.
      await tester.pump();
      await tester.pump(const Duration(seconds: 1));

      // The simulation actually did stuff after start ballistics.
      expect(scrolledPositions.length, greaterThan(50));
      // Though it still lands back to the same item with the same scroll offset.
      expect(controller.selectedItem, 40);
      expect(scrolledPositions.last, moreOrLessEquals(40 * 1000.0, epsilon: 0.2));
    });

    testWidgets('high fling velocities lands exactly on items', (WidgetTester tester) async {
      final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 40);
      final List<double> scrolledPositions = <double>[];

      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: NotificationListener<ScrollNotification>(
            onNotification: (ScrollNotification notification) {
              if (notification is ScrollUpdateNotification)
                scrolledPositions.add(notification.metrics.pixels);
              return false;
            },
            child: ListWheelScrollView(
              controller: controller,
              physics: const FixedExtentScrollPhysics(),
              itemExtent: 100.0,
              children: List<Widget>.generate(100, (int index) {
                return const Placeholder();
              }),
            ),
          ),
        ),
      );

      await tester.fling(
        find.byType(ListWheelScrollView),
        // High and random numbers that's unlikely to land on exact multiples of 100.
        const Offset(0.0, -567.0),
        678.0,
      );

      // After the drag, 40 + 567px should be on the 46th item.
      expect(controller.selectedItem, 46);
      // A tester.fling creates and pumps 50 pointer events.
      expect(scrolledPositions.length, 50);
      // iOS flings ease-in initially.
      expect(scrolledPositions.last, moreOrLessEquals(40 * 100.0 + 556.826666666673, epsilon: 0.2));

      // Let the spring back simulation finish.
      await tester.pumpAndSettle();

      // The simulation actually did stuff after start ballistics.
      expect(scrolledPositions.length, greaterThan(50));
      // Lands on 49.
      expect(controller.selectedItem, 49);
      // More importantly, lands tightly on 49.
      expect(scrolledPositions.last, moreOrLessEquals(49 * 100.0, epsilon: 0.3));
    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
  });

  testWidgets('ListWheelScrollView getOffsetToReveal', (WidgetTester tester) async {
    List<Widget> outerChildren;
    final List<Widget> innerChildren = List<Widget>.generate(10, (int index) => Container());

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: SizedBox(
            height: 500.0,
            width: 300.0,
            child: ListWheelScrollView(
              controller: ScrollController(initialScrollOffset: 300.0),
              itemExtent: 100.0,
              children: outerChildren = List<Widget>.generate(10, (int i) {
                return Center(
                  child: innerChildren[i] = SizedBox(
                    height: 50.0,
                    width: 50.0,
                    child: Text('Item $i'),
                  ),
                );
              }),
            ),
          ),
        ),
      ),
    );

    final RenderListWheelViewport viewport = tester.allRenderObjects.whereType<RenderListWheelViewport>().first;

    // direct child of viewport
    RenderObject target = tester.renderObject(find.byWidget(outerChildren[5]));
    RevealedOffset revealed = viewport.getOffsetToReveal(target, 0.0);
    expect(revealed.offset, 500.0);
    expect(revealed.rect, const Rect.fromLTWH(0.0, 200.0, 300.0, 100.0));

    revealed = viewport.getOffsetToReveal(target, 1.0);
    expect(revealed.offset, 500.0);
    expect(revealed.rect, const Rect.fromLTWH(0.0, 200.0, 300.0, 100.0));

    revealed = viewport.getOffsetToReveal(target, 0.0, rect: const Rect.fromLTWH(40.0, 40.0, 10.0, 10.0));
    expect(revealed.offset, 500.0);
    expect(revealed.rect, const Rect.fromLTWH(40.0, 240.0, 10.0, 10.0));

    revealed = viewport.getOffsetToReveal(target, 1.0, rect: const Rect.fromLTWH(40.0, 40.0, 10.0, 10.0));
    expect(revealed.offset, 500.0);
    expect(revealed.rect, const Rect.fromLTWH(40.0, 240.0, 10.0, 10.0));

    // descendant of viewport, not direct child
    target = tester.renderObject(find.byWidget(innerChildren[5]));
    revealed = viewport.getOffsetToReveal(target, 0.0);
    expect(revealed.offset, 500.0);
    expect(revealed.rect, const Rect.fromLTWH(125.0, 225.0, 50.0, 50.0));

    revealed = viewport.getOffsetToReveal(target, 1.0);
    expect(revealed.offset, 500.0);
    expect(revealed.rect, const Rect.fromLTWH(125.0, 225.0, 50.0, 50.0));

    revealed = viewport.getOffsetToReveal(target, 0.0, rect: const Rect.fromLTWH(40.0, 40.0, 10.0, 10.0));
    expect(revealed.offset, 500.0);
    expect(revealed.rect, const Rect.fromLTWH(165.0, 265.0, 10.0, 10.0));

    revealed = viewport.getOffsetToReveal(target, 1.0, rect: const Rect.fromLTWH(40.0, 40.0, 10.0, 10.0));
    expect(revealed.offset, 500.0);
    expect(revealed.rect, const Rect.fromLTWH(165.0, 265.0, 10.0, 10.0));
  });

  testWidgets('ListWheelScrollView showOnScreen', (WidgetTester tester) async {
    List<Widget> outerChildren;
    final List<Widget> innerChildren = List<Widget>.generate(10, (int index) => Container());
    ScrollController controller;

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Center(
          child: SizedBox(
            height: 500.0,
            width: 300.0,
            child: ListWheelScrollView(
              controller: controller = ScrollController(initialScrollOffset: 300.0),
              itemExtent: 100.0,
              children:
              outerChildren = List<Widget>.generate(10, (int i) {
                return Center(
                  child: innerChildren[i] = SizedBox(
                    height: 50.0,
                    width: 50.0,
                    child: Text('Item $i'),
                  ),
                );
              }),
            ),
          ),
        ),
      ),
    );

    expect(controller.offset, 300.0);

    tester.renderObject(find.byWidget(outerChildren[5])).showOnScreen();
    await tester.pumpAndSettle();
    expect(controller.offset, 500.0);

    tester.renderObject(find.byWidget(outerChildren[7])).showOnScreen();
    await tester.pumpAndSettle();
    expect(controller.offset, 700.0);

    tester.renderObject(find.byWidget(innerChildren[9])).showOnScreen();
    await tester.pumpAndSettle();
    expect(controller.offset, 900.0);

    tester.renderObject(find.byWidget(outerChildren[7])).showOnScreen(duration: const Duration(seconds: 2));
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));
    expect(tester.hasRunningAnimations, isTrue);
    expect(controller.offset, lessThan(900.0));
    expect(controller.offset, greaterThan(700.0));
    await tester.pumpAndSettle();
    expect(controller.offset, 700.0);
  });
}
