// 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/widgets.dart';
import 'package:flutter_test/flutter_test.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: const SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: SizedBox(
                width: 600.0,
                child: 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(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: ScrollConfiguration(
          behavior: TestScrollBehavior1(),
          child: 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(
      const Directionality(
        textDirection: TextDirection.ltr,
        child: ScrollConfiguration(
          behavior: TestScrollBehavior2(),
          child: 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: const 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: const 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 {
  const TestScrollBehavior1();

  @override
  Widget buildOverscrollIndicator(BuildContext context, Widget child, ScrollableDetails details) {
    return GlowingOverscrollIndicator(
      axisDirection: details.direction,
      color: const Color(0xFF00FF00),
      child: child,
    );
  }
}

class TestScrollBehavior2 extends ScrollBehavior {
  const TestScrollBehavior2();

  @override
  Widget buildOverscrollIndicator(BuildContext context, Widget child, ScrollableDetails details) {
    return GlowingOverscrollIndicator(
      axisDirection: details.direction,
      color: const Color(0xFF0000FF),
      child: child,
    );
  }
}
