// 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 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';

// Assuming that the test container is 800x600. The height of the
// viewport's contents is 650.0, the top and bottom text children
// are 100 pixels high and top/left edge of both widgets are visible.
// The top of the bottom widget is at 550 (the top of the top widget
// is at 0). The top of the bottom widget is 500 when it has been
// scrolled completely into view.
Widget buildFrame(ScrollPhysics physics, { ScrollController scrollController }) {
  return SingleChildScrollView(
    key: UniqueKey(),
    physics: physics,
    controller: scrollController,
    child: SizedBox(
      height: 650.0,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        textDirection: TextDirection.ltr,
        children: <Widget>[
          const SizedBox(height: 100.0, child: Text('top', textDirection: TextDirection.ltr)),
          Expanded(child: Container()),
          const SizedBox(height: 100.0, child: Text('bottom', textDirection: TextDirection.ltr)),
        ],
      ),
    ),
  );
}

void main() {
  testWidgets('ClampingScrollPhysics', (WidgetTester tester) async {

    // Scroll the target text widget by offset and then return its origin
    // in global coordinates.
    Future<Offset> locationAfterScroll(String target, Offset offset) async {
      await tester.dragFrom(tester.getTopLeft(find.text(target)), offset);
      await tester.pump();
      final RenderBox textBox = tester.renderObject(find.text(target));
      final Offset widgetOrigin = textBox.localToGlobal(Offset.zero);
      await tester.pump(const Duration(seconds: 1)); // Allow overscroll to settle
      return Future<Offset>.value(widgetOrigin);
    }

    await tester.pumpWidget(buildFrame(const BouncingScrollPhysics()));
    Offset origin = await locationAfterScroll('top', const Offset(0.0, 400.0));
    expect(origin.dy, greaterThan(0.0));
    origin = await locationAfterScroll('bottom', const Offset(0.0, -400.0));
    expect(origin.dy, lessThan(500.0));


    await tester.pumpWidget(buildFrame(const ClampingScrollPhysics()));
    origin = await locationAfterScroll('top', const Offset(0.0, 400.0));
    expect(origin.dy, equals(0.0));
    origin = await locationAfterScroll('bottom', const Offset(0.0, -400.0));
    expect(origin.dy, equals(500.0));
  });

  testWidgets('ClampingScrollPhysics affects ScrollPosition', (WidgetTester tester) async {

    // BouncingScrollPhysics

    await tester.pumpWidget(buildFrame(const BouncingScrollPhysics()));
    ScrollableState scrollable = tester.state(find.byType(Scrollable));

    await tester.dragFrom(tester.getTopLeft(find.text('top')), const Offset(0.0, 400.0));
    await tester.pump();
    expect(scrollable.position.pixels, lessThan(0.0));
    await tester.pump(const Duration(seconds: 1)); // Allow overscroll to settle

    await tester.dragFrom(tester.getTopLeft(find.text('bottom')), const Offset(0.0, -400.0));
    await tester.pump();
    expect(scrollable.position.pixels, greaterThan(0.0));
    await tester.pump(const Duration(seconds: 1)); // Allow overscroll to settle

    // ClampingScrollPhysics

    await tester.pumpWidget(buildFrame(const ClampingScrollPhysics()));
    scrollable = scrollable = tester.state(find.byType(Scrollable));

    await tester.dragFrom(tester.getTopLeft(find.text('top')), const Offset(0.0, 400.0));
    await tester.pump();
    expect(scrollable.position.pixels, equals(0.0));
    await tester.pump(const Duration(seconds: 1)); // Allow overscroll to settle

    await tester.dragFrom(tester.getTopLeft(find.text('bottom')), const Offset(0.0, -400.0));
    await tester.pump();
    expect(scrollable.position.pixels, equals(50.0));
  });

  testWidgets('ClampingScrollPhysics handles out of bounds ScrollPosition', (WidgetTester tester) async {
    Future<void> testOutOfBounds(ScrollPhysics physics, double initialOffset, double expectedOffset) async {
      final ScrollController scrollController = ScrollController(initialScrollOffset: initialOffset);
      await tester.pumpWidget(buildFrame(physics, scrollController: scrollController));
      final ScrollableState scrollable = tester.state(find.byType(Scrollable));

      expect(scrollable.position.pixels, equals(initialOffset));
      await tester.pump(const Duration(seconds: 1)); // Allow overscroll to settle
      expect(scrollable.position.pixels, equals(expectedOffset));
    }

    await testOutOfBounds(const ClampingScrollPhysics(), -400.0, 0.0);
    await testOutOfBounds(const ClampingScrollPhysics(), 800.0, 50.0);
  });
}
