// 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:math' as math;

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

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

final Matcher doesNotOverscroll = isNot(paints..circle());

Future<void> slowDrag(WidgetTester tester, Offset start, Offset offset) async {
  final TestGesture gesture = await tester.startGesture(start);
  for (int index = 0; index < 10; index += 1) {
    await gesture.moveBy(offset);
    await tester.pump(const Duration(milliseconds: 20));
  }
  await gesture.up();
}

void main() {
  testWidgets('Overscroll indicator color', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: CustomScrollView(
          slivers: <Widget>[
            SliverToBoxAdapter(child: SizedBox(height: 2000.0)),
          ],
        ),
      ),
    );
    final RenderObject painter = tester.renderObject(find.byType(CustomPaint));

    expect(painter, doesNotOverscroll);

    // the scroll gesture from tester.scroll happens in zero time, so nothing should appear:
    await tester.drag(find.byType(Scrollable), const Offset(0.0, 100.0));
    expect(painter, doesNotOverscroll);
    await tester.pump(); // allow the ticker to register itself
    expect(painter, doesNotOverscroll);
    await tester.pump(const Duration(milliseconds: 100)); // animate
    expect(painter, doesNotOverscroll);

    final TestGesture gesture = await tester.startGesture(const Offset(200.0, 200.0));
    await tester.pump(const Duration(milliseconds: 100)); // animate
    expect(painter, doesNotOverscroll);
    await gesture.up();
    expect(painter, doesNotOverscroll);

    await slowDrag(tester, const Offset(200.0, 200.0), const Offset(0.0, 5.0));
    expect(painter, paints..circle(color: const Color(0x0DFFFFFF)));

    await tester.pumpAndSettle(const Duration(seconds: 1));
    expect(painter, doesNotOverscroll);
  });

  testWidgets('Nested scrollable', (WidgetTester tester) async {
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: GlowingOverscrollIndicator(
          axisDirection: AxisDirection.down,
          color: const Color(0x0DFFFFFF),
          notificationPredicate: (ScrollNotification notification) => notification.depth == 1,
          child: SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: Container(
                width: 600.0,
                child: const CustomScrollView(
                  slivers: <Widget>[
                    SliverToBoxAdapter(child: SizedBox(height: 2000.0)),
                  ],
                ),
              ),
            ),
          ),
        ),
      );

    final RenderObject outerPainter = tester.renderObject(find.byType(CustomPaint).first);
    final RenderObject innerPainter = tester.renderObject(find.byType(CustomPaint).last);

    await slowDrag(tester, const Offset(200.0, 200.0), const Offset(0.0, 5.0));
    expect(outerPainter, paints..circle());
    expect(innerPainter, paints..circle());
  });

  testWidgets('Overscroll indicator changes side when you drag on the other side', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: CustomScrollView(
          slivers: <Widget>[
            SliverToBoxAdapter(child: SizedBox(height: 2000.0)),
          ],
        ),
      ),
    );
    final RenderObject painter = tester.renderObject(find.byType(CustomPaint));

    await slowDrag(tester, const Offset(400.0, 200.0), const Offset(0.0, 10.0));
    expect(painter, paints..circle(x: 400.0));
    await slowDrag(tester, const Offset(100.0, 200.0), const Offset(0.0, 10.0));
    expect(painter, paints..something((Symbol method, List<dynamic> arguments) {
      if (method != #drawCircle)
        return false;
      final Offset center = arguments[0] as Offset;
      if (center.dx < 400.0)
        return true;
      throw 'Dragging on left hand side did not overscroll on left hand side.';
    }));
    await slowDrag(tester, const Offset(700.0, 200.0), const Offset(0.0, 10.0));
    expect(painter, paints..something((Symbol method, List<dynamic> arguments) {
      if (method != #drawCircle)
        return false;
      final Offset center = arguments[0] as Offset;
      if (center.dx > 400.0)
        return true;
      throw 'Dragging on right hand side did not overscroll on right hand side.';
    }));

    await tester.pumpAndSettle(const Duration(seconds: 1));
    expect(painter, doesNotOverscroll);
  });

  testWidgets('Overscroll indicator changes side when you shift sides', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: CustomScrollView(
          slivers: <Widget>[
            SliverToBoxAdapter(child: SizedBox(height: 2000.0)),
          ],
        ),
      ),
    );
    final RenderObject painter = tester.renderObject(find.byType(CustomPaint));
    final TestGesture gesture = await tester.startGesture(const Offset(300.0, 200.0));
    await gesture.moveBy(const Offset(0.0, 10.0));
    await tester.pump(const Duration(milliseconds: 20));
    double oldX = 0.0;
    for (int index = 0; index < 10; index += 1) {
      await gesture.moveBy(const Offset(50.0, 50.0));
      await tester.pump(const Duration(milliseconds: 20));
      expect(painter, paints..something((Symbol method, List<dynamic> arguments) {
        if (method != #drawCircle)
          return false;
        final Offset center = arguments[0] as Offset;
        if (center.dx <= oldX)
          throw 'Sliding to the right did not make the center of the radius slide to the right.';
        oldX = center.dx;
        return true;
      }));
    }
    await gesture.up();

    await tester.pumpAndSettle(const Duration(seconds: 1));
    expect(painter, doesNotOverscroll);
  });

  group("Flipping direction of scrollable doesn't change overscroll behavior", () {
    testWidgets('down', (WidgetTester tester) async {
      await tester.pumpWidget(
        const Directionality(
          textDirection: TextDirection.ltr,
          child: CustomScrollView(
            physics: AlwaysScrollableScrollPhysics(),
            slivers: <Widget>[
              SliverToBoxAdapter(child: SizedBox(height: 20.0)),
            ],
          ),
        ),
      );
      final RenderObject painter = tester.renderObject(find.byType(CustomPaint));
      await slowDrag(tester, const Offset(200.0, 200.0), const Offset(0.0, 5.0));
      expect(painter, paints..save()..circle()..restore()..save()..scale(y: -1.0)..restore()..restore());

      await tester.pumpAndSettle(const Duration(seconds: 1));
      expect(painter, doesNotOverscroll);
    });

    testWidgets('up', (WidgetTester tester) async {
      await tester.pumpWidget(
        const Directionality(
          textDirection: TextDirection.ltr,
          child: CustomScrollView(
            reverse: true,
            physics: AlwaysScrollableScrollPhysics(),
            slivers: <Widget>[
              SliverToBoxAdapter(child: SizedBox(height: 20.0)),
            ],
          ),
        ),
      );
      final RenderObject painter = tester.renderObject(find.byType(CustomPaint));
      await slowDrag(tester, const Offset(200.0, 200.0), const Offset(0.0, 5.0));
      expect(painter, paints..save()..scale(y: -1.0)..restore()..save()..circle()..restore()..restore());

      await tester.pumpAndSettle(const Duration(seconds: 1));
      expect(painter, doesNotOverscroll);
    });
  });

  testWidgets('Overscroll in both directions', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: CustomScrollView(
          physics: AlwaysScrollableScrollPhysics(),
          slivers: <Widget>[
            SliverToBoxAdapter(child: SizedBox(height: 20.0)),
          ],
        ),
      ),
    );
    final RenderObject painter = tester.renderObject(find.byType(CustomPaint));
    await slowDrag(tester, const Offset(200.0, 200.0), const Offset(0.0, 5.0));
    expect(painter, paints..circle());
    expect(painter, isNot(paints..circle()..circle()));
    await slowDrag(tester, const Offset(200.0, 200.0), const Offset(0.0, -5.0));
    expect(painter, paints..circle()..circle());

    await tester.pumpAndSettle(const Duration(seconds: 1));
    expect(painter, doesNotOverscroll);
  });

  testWidgets('Overscroll horizontally', (WidgetTester tester) async {
    await tester.pumpWidget(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: CustomScrollView(
          scrollDirection: Axis.horizontal,
          physics: AlwaysScrollableScrollPhysics(),
          slivers: <Widget>[
            SliverToBoxAdapter(child: SizedBox(height: 20.0)),
          ],
        ),
      ),
    );
    final RenderObject painter = tester.renderObject(find.byType(CustomPaint));
    await slowDrag(tester, const Offset(200.0, 200.0), const Offset(5.0, 0.0));
    expect(painter, paints..rotate(angle: math.pi / 2.0)..circle()..saveRestore());
    expect(painter, isNot(paints..circle()..circle()));
    await slowDrag(tester, const Offset(200.0, 200.0), const Offset(-5.0, 0.0));
    expect(painter, paints..rotate(angle: math.pi / 2.0)..circle()
                          ..rotate(angle: math.pi / 2.0)..circle());

    await tester.pumpAndSettle(const Duration(seconds: 1));
    expect(painter, doesNotOverscroll);
  });

  testWidgets('Nested overscrolls do not throw exceptions', (WidgetTester tester) async {
    await tester.pumpWidget(Directionality(
      textDirection: TextDirection.ltr,
      child: PageView(
        children: <Widget>[
          ListView(
            children: <Widget>[
              Container(
                width: 2000.0,
                height: 2000.0,
                color: const Color(0xFF00FF00),
              ),
            ],
          ),
        ],
      ),
    ));

    await tester.dragFrom(const Offset(100.0, 100.0), const Offset(0.0, 2000.0));
    await tester.pumpAndSettle();
  });

  testWidgets('Changing settings', (WidgetTester tester) async {
    RenderObject painter;

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ScrollConfiguration(
          behavior: TestScrollBehavior1(),
          child: const CustomScrollView(
            scrollDirection: Axis.horizontal,
            physics: AlwaysScrollableScrollPhysics(),
            reverse: true,
            slivers: <Widget>[
              SliverToBoxAdapter(child: SizedBox(height: 20.0)),
            ],
          ),
        ),
      ),
    );
    painter = tester.renderObject(find.byType(CustomPaint));
    await slowDrag(tester, const Offset(200.0, 200.0), const Offset(5.0, 0.0));
    expect(painter, paints..rotate(angle: math.pi / 2.0)..circle(color: const Color(0x0A00FF00)));
    expect(painter, isNot(paints..circle()..circle()));

    await tester.pumpAndSettle(const Duration(seconds: 1));
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ScrollConfiguration(
          behavior: TestScrollBehavior2(),
          child: const CustomScrollView(
            scrollDirection: Axis.horizontal,
            physics: AlwaysScrollableScrollPhysics(),
            slivers: <Widget>[
              SliverToBoxAdapter(child: SizedBox(height: 20.0)),
            ],
          ),
        ),
      ),
    );
    painter = tester.renderObject(find.byType(CustomPaint));
    await slowDrag(tester, const Offset(200.0, 200.0), const Offset(5.0, 0.0));
    expect(painter, paints..rotate(angle: math.pi / 2.0)..circle(color: const Color(0x0A0000FF))..saveRestore());
    expect(painter, isNot(paints..circle()..circle()));
  });

  testWidgets('CustomScrollView overscroll indicator works if there is sliver before center', (WidgetTester tester) async {
    final Key centerKey = UniqueKey();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ScrollConfiguration(
          behavior: TestScrollBehavior2(),
          child: CustomScrollView(
            center: centerKey,
            physics: const AlwaysScrollableScrollPhysics(),
            slivers: <Widget>[
              SliverList(
                delegate: SliverChildBuilderDelegate(
                    (BuildContext context, int index) => Text('First sliver $index',),
                  childCount: 2,
                ),
              ),
              SliverList(
                key: centerKey,
                delegate: SliverChildBuilderDelegate(
                    (BuildContext context, int index) => Text('Second sliver $index',),
                  childCount: 5,
                ),
              ),
            ],
          ),
        ),
      ),
    );

    expect(find.text('First sliver 1'), findsNothing);

    await slowDrag(tester, const Offset(200.0, 200.0), const Offset(0.0, 300.0));
    expect(find.text('First sliver 1'), findsOneWidget);
    final RenderObject painter = tester.renderObject(find.byType(CustomPaint));
    // The scroll offset and paint extend should cancel out each other.
    expect(painter, paints..save()..translate(y: 0.0)..scale()..circle());
  });

  testWidgets('CustomScrollView overscroll indicator works well with [CustomScrollView.center] and [OverscrollIndicatorNotification.paintOffset]', (WidgetTester tester) async {
    final Key centerKey = UniqueKey();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ScrollConfiguration(
          behavior: TestScrollBehavior2(),
          child: NotificationListener<OverscrollIndicatorNotification>(
            onNotification: (OverscrollIndicatorNotification notification) {
              if (notification.leading) {
                notification.paintOffset = 50.0;
              }
              return false;
            },
            child: CustomScrollView(
              center: centerKey,
              physics: const AlwaysScrollableScrollPhysics(),
              slivers: <Widget>[
                SliverList(
                  delegate: SliverChildBuilderDelegate(
                        (BuildContext context, int index) => Text('First sliver $index',),
                    childCount: 2,
                  ),
                ),
                SliverList(
                  key: centerKey,
                  delegate: SliverChildBuilderDelegate(
                        (BuildContext context, int index) => Text('Second sliver $index',),
                    childCount: 5,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );

    expect(find.text('First sliver 1'), findsNothing);

    await slowDrag(tester, const Offset(200.0, 200.0), const Offset(0.0, 5.0)); // offset will be magnified ten times
    expect(find.text('First sliver 1'), findsOneWidget);
    final RenderObject painter = tester.renderObject(find.byType(CustomPaint));
    // The OverscrollIndicator should respect the [OverscrollIndicatorNotification.paintOffset] setting.
    expect(painter, paints..save()..translate(y: 50.0)..scale()..circle());
  });

  testWidgets('The OverscrollIndicator should not overflow the scrollable view edge', (WidgetTester tester) async {
    // Regressing test for https://github.com/flutter/flutter/issues/64149
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: NotificationListener<OverscrollIndicatorNotification>(
          onNotification: (OverscrollIndicatorNotification notification) {
            notification.paintOffset = 50.0; // both the leading and trailing indicator have a 50.0 pixels offset.
            return false;
          },
          child: const CustomScrollView(
            slivers: <Widget>[
              SliverToBoxAdapter(child: SizedBox(height: 2000.0)),
            ],
          ),
        ),
      ),
    );
    final RenderObject painter = tester.renderObject(find.byType(CustomPaint));
    await slowDrag(tester, const Offset(200.0, 200.0), const Offset(0.0, 5.0));
    expect(painter, paints..save()..translate(y: 50.0)..scale()..circle());
    // Reverse scroll (30 pixels), and the offset < notification.paintOffset.
    await tester.dragFrom(const Offset(200.0, 200.0), const Offset(0.0, -30.0));
    await tester.pump();
    // The OverscrollIndicator should move with the CustomScrollView.
    expect(painter, paints..save()..translate(y: 50.0 - 30.0)..scale()..circle());

    // Reverse scroll (30+20 pixels) and offset == notification.paintOffset.
    await tester.dragFrom(const Offset(200.0, 200.0), const Offset(0.0, -20.0));
    await tester.pump();
    expect(painter, paints..save()..translate(y: 50.0 - 50.0)..scale()..circle());

    // Reverse scroll (30+20+10 pixels) and offset > notification.paintOffset.
    await tester.dragFrom(const Offset(200.0, 200.0), const Offset(0.0, -10.0));
    await tester.pump();
    // The OverscrollIndicator should not overflow the CustomScrollView's edge.
    expect(painter, paints..save()..translate(y: 50.0 - 50.0)..scale()..circle());

    await tester.pumpAndSettle(); // Finish the leading indicator.

    // trigger the trailing indicator
    await slowDrag(tester, const Offset(200.0, 200.0), const Offset(0.0, -200.0));
    expect(painter, paints..scale(y: -1.0)..save()..translate(y: 50.0)..scale()..circle());

    // Reverse scroll (30 pixels), and the offset < notification.paintOffset.
    await tester.dragFrom(const Offset(200.0, 200.0), const Offset(0.0, 30.0));
    await tester.pump();
    // The OverscrollIndicator should move with the CustomScrollView.
    expect(painter, paints..scale(y: -1.0)..save()..translate(y: 50.0 - 30.0)..scale()..circle());

    // Reverse scroll (30+20 pixels) and offset == notification.paintOffset.
    await tester.dragFrom(const Offset(200.0, 200.0), const Offset(0.0, 20.0));
    await tester.pump();
    expect(painter, paints..scale(y: -1.0)..save()..translate(y: 50.0 - 50.0)..scale()..circle());

    // Reverse scroll (30+20+10 pixels) and offset > notification.paintOffset.
    await tester.dragFrom(const Offset(200.0, 200.0), const Offset(0.0, 10.0));
    await tester.pump();
    // The OverscrollIndicator should not overflow the CustomScrollView's edge.
    expect(painter, paints..scale(y: -1.0)..save()..translate(y: 50.0 - 50.0)..scale()..circle());
  });

  group('[OverscrollIndicatorNotification.paintOffset] test', () {
    testWidgets('Leading', (WidgetTester tester) async {
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: NotificationListener<OverscrollIndicatorNotification>(
            onNotification: (OverscrollIndicatorNotification notification) {
              if (notification.leading) {
                notification.paintOffset = 50.0;
              }
              return false;
            },
            child: const CustomScrollView(
              slivers: <Widget>[
                SliverToBoxAdapter(child: SizedBox(height: 2000.0)),
              ],
            ),
          ),
        ),
      );
      final RenderObject painter = tester.renderObject(find.byType(CustomPaint));
      await slowDrag(tester, const Offset(200.0, 200.0), const Offset(0.0, 5.0));
      // The OverscrollIndicator should respect the [OverscrollIndicatorNotification.paintOffset] setting.
      expect(painter, paints..save()..translate(y: 50.0)..scale()..circle());
      // Reverse scroll direction.
      await tester.dragFrom(const Offset(200.0, 200.0), const Offset(0.0, -30.0));
      await tester.pump();
      // The OverscrollIndicator should move with the CustomScrollView.
      expect(painter, paints..save()..translate(y: 50.0 - 30.0)..scale()..circle());
    });

    testWidgets('Trailing', (WidgetTester tester) async {
      await tester.pumpWidget(
        Directionality(
          textDirection: TextDirection.ltr,
          child: NotificationListener<OverscrollIndicatorNotification>(
            onNotification: (OverscrollIndicatorNotification notification) {
              if (!notification.leading) {
                notification.paintOffset = 50.0;
              }
              return false;
            },
            child: const CustomScrollView(
              slivers: <Widget>[
                SliverToBoxAdapter(child: SizedBox(height: 2000.0)),
              ],
            ),
          ),
        ),
      );
      final RenderObject painter = tester.renderObject(find.byType(CustomPaint));
      await tester.dragFrom(const Offset(200.0, 200.0), const Offset(200.0, -10000.0));
      await tester.pump();
      await slowDrag(tester, const Offset(200.0, 200.0), const Offset(0.0, -5.0));
      // The OverscrollIndicator should respect the [OverscrollIndicatorNotification.paintOffset] setting.
      expect(painter, paints..scale(y: -1.0)..save()..translate(y: 50.0)..scale()..circle());
      // Reverse scroll direction.
      await tester.dragFrom(const Offset(200.0, 200.0), const Offset(0.0, 30.0));
      await tester.pump();
      // The OverscrollIndicator should move with the CustomScrollView.
      expect(painter, paints..scale(y: -1.0)..save()..translate(y: 50.0 - 30.0)..scale()..circle());
    });
  });
}

class TestScrollBehavior1 extends ScrollBehavior {
  @override
  Widget buildViewportChrome(BuildContext context, Widget child, AxisDirection axisDirection) {
    return GlowingOverscrollIndicator(
      child: child,
      axisDirection: axisDirection,
      color: const Color(0xFF00FF00),
    );
  }
}

class TestScrollBehavior2 extends ScrollBehavior {
  @override
  Widget buildViewportChrome(BuildContext context, Widget child, AxisDirection axisDirection) {
    return GlowingOverscrollIndicator(
      child: child,
      axisDirection: axisDirection,
      color: const Color(0xFF0000FF),
    );
  }
}
