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

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

import 'states.dart';

void main() {
  testWidgets('ScrollController control test', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ListView(
          controller: controller,
          children: kStates.map<Widget>((String state) {
            return SizedBox(
              height: 200.0,
              child: Text(state),
            );
          }).toList(),
        ),
      ),
    );

    double realOffset() {
      return tester.state<ScrollableState>(find.byType(Scrollable)).position.pixels;
    }

    expect(controller.offset, equals(0.0));
    expect(realOffset(), equals(controller.offset));

    controller.jumpTo(653.0);

    expect(controller.offset, equals(653.0));
    expect(realOffset(), equals(controller.offset));

    await tester.pump();

    expect(controller.offset, equals(653.0));
    expect(realOffset(), equals(controller.offset));

    controller.animateTo(326.0, duration: const Duration(milliseconds: 300), curve: Curves.ease);
    await tester.pumpAndSettle();

    expect(controller.offset, equals(326.0));
    expect(realOffset(), equals(controller.offset));

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ListView(
          key: const Key('second'),
          controller: controller,
          children: kStates.map<Widget>((String state) {
            return SizedBox(
              height: 200.0,
              child: Text(state),
            );
          }).toList(),
        ),
      ),
    );

    expect(controller.offset, equals(0.0));
    expect(realOffset(), equals(controller.offset));

    controller.jumpTo(653.0);

    expect(controller.offset, equals(653.0));
    expect(realOffset(), equals(controller.offset));

    final ScrollController controller2 = ScrollController();

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ListView(
          key: const Key('second'),
          controller: controller2,
          children: kStates.map<Widget>((String state) {
            return SizedBox(
              height: 200.0,
              child: Text(state),
            );
          }).toList(),
        ),
      ),
    );

    expect(() => controller.offset, throwsAssertionError);
    expect(controller2.offset, equals(653.0));
    expect(realOffset(), equals(controller2.offset));

    expect(() => controller.jumpTo(120.0), throwsAssertionError);
    expect(() => controller.animateTo(132.0, duration: const Duration(milliseconds: 300), curve: Curves.ease), throwsAssertionError);

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ListView(
          key: const Key('second'),
          controller: controller2,
          physics: const BouncingScrollPhysics(),
          children: kStates.map<Widget>((String state) {
            return SizedBox(
              height: 200.0,
              child: Text(state),
            );
          }).toList(),
        ),
      ),
    );

    expect(controller2.offset, equals(653.0));
    expect(realOffset(), equals(controller2.offset));

    controller2.jumpTo(432.0);

    expect(controller2.offset, equals(432.0));
    expect(realOffset(), equals(controller2.offset));

    await tester.pump();

    expect(controller2.offset, equals(432.0));
    expect(realOffset(), equals(controller2.offset));
  });

  testWidgets('ScrollController control test', (WidgetTester tester) async {
    final ScrollController controller = ScrollController(
      initialScrollOffset: 209.0,
    );

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: GridView.count(
          crossAxisCount: 4,
          controller: controller,
          children: kStates.map<Widget>((String state) => Text(state)).toList(),
        ),
      ),
    );

    double realOffset() {
      return tester.state<ScrollableState>(find.byType(Scrollable)).position.pixels;
    }

    expect(controller.offset, equals(209.0));
    expect(realOffset(), equals(controller.offset));

    controller.jumpTo(105.0);

    await tester.pump();

    expect(controller.offset, equals(105.0));
    expect(realOffset(), equals(controller.offset));

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: GridView.count(
          crossAxisCount: 2,
          controller: controller,
          children: kStates.map<Widget>((String state) => Text(state)).toList(),
        ),
      ),
    );

    expect(controller.offset, equals(105.0));
    expect(realOffset(), equals(controller.offset));
  });

  testWidgets('DrivenScrollActivity ending after dispose', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ListView(
          controller: controller,
          children: <Widget>[ Container(height: 200000.0) ],
        ),
      ),
    );

    controller.animateTo(1000.0, duration: const Duration(seconds: 1), curve: Curves.linear);

    await tester.pump(); // Start the animation.

    // We will now change the tree on the same frame as the animation ends.
    await tester.pumpWidget(Container(), const Duration(seconds: 2));
  });

  testWidgets('Read operations on ScrollControllers with no positions fail', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    expect(() => controller.offset, throwsAssertionError);
    expect(() => controller.position, throwsAssertionError);
  });

  testWidgets('Read operations on ScrollControllers with more than one position fail', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ListView(
          children: <Widget>[
            Container(
              constraints: const BoxConstraints(maxHeight: 500.0),
              child: ListView(
                controller: controller,
                children: kStates.map<Widget>((String state) {
                  return SizedBox(height: 200.0, child: Text(state));
                }).toList(),
              ),
            ),
            Container(
              constraints: const BoxConstraints(maxHeight: 500.0),
              child: ListView(
                controller: controller,
                children: kStates.map<Widget>((String state) {
                  return SizedBox(height: 200.0, child: Text(state));
                }).toList(),
              ),
            ),
          ],
        ),
      ),
    );

    expect(() => controller.offset, throwsAssertionError);
    expect(() => controller.position, throwsAssertionError);
  });

  testWidgets('Write operations on ScrollControllers with no positions fail', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    expect(() => controller.animateTo(1.0, duration: const Duration(seconds: 1), curve: Curves.linear), throwsAssertionError);
    expect(() => controller.jumpTo(1.0), throwsAssertionError);
  });

  testWidgets('Write operations on ScrollControllers with more than one position do not throw', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ListView(
          children: <Widget>[
            Container(
              constraints: const BoxConstraints(maxHeight: 500.0),
              child: ListView(
                controller: controller,
                children: kStates.map<Widget>((String state) {
                  return SizedBox(height: 200.0, child: Text(state));
                }).toList(),
              ),
            ),
            Container(
              constraints: const BoxConstraints(maxHeight: 500.0),
              child: ListView(
                controller: controller,
                children: kStates.map<Widget>((String state) {
                  return SizedBox(height: 200.0, child: Text(state));
                }).toList(),
              ),
            ),
          ],
        ),
      ),
    );

    controller.jumpTo(1.0);
    controller.animateTo(1.0, duration: const Duration(seconds: 1), curve: Curves.linear);
    await tester.pumpAndSettle();
  });

  testWidgets('Scroll controllers notify when the position changes', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();

    final List<double> log = <double>[];

    controller.addListener(() {
      log.add(controller.offset);
    });

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: ListView(
          controller: controller,
          children: kStates.map<Widget>((String state) {
            return SizedBox(height: 200.0, child: Text(state));
          }).toList(),
        ),
      ),
    );

    expect(log, isEmpty);

    await tester.drag(find.byType(ListView), const Offset(0.0, -250.0));

    expect(log, equals(<double>[ 20.0, 250.0 ]));
    log.clear();

    controller.dispose();

    await tester.drag(find.byType(ListView), const Offset(0.0, -130.0));
    expect(log, isEmpty);
  });

  testWidgets('keepScrollOffset', (WidgetTester tester) async {
    final PageStorageBucket bucket = PageStorageBucket();

    Widget buildFrame(ScrollController controller) {
      return Directionality(
        textDirection: TextDirection.ltr,
        child: PageStorage(
          bucket: bucket,
          child: KeyedSubtree(
            key: const PageStorageKey<String>('ListView'),
            child: ListView(
              key: UniqueKey(), // it's a different ListView every time
              controller: controller,
              children: List<Widget>.generate(50, (int index) {
                return SizedBox(height: 100.0, child: Text('Item $index'));
              }).toList(),
            ),
          ),
        ),
      );
    }

    // keepScrollOffset: true (the default). The scroll offset is restored
    // when the ListView is recreated with a new ScrollController.

    // The initialScrollOffset is used in this case, because there's no saved
    // scroll offset.
    ScrollController controller = ScrollController(initialScrollOffset: 200.0);
    await tester.pumpWidget(buildFrame(controller));
    expect(tester.getTopLeft(find.widgetWithText(SizedBox, 'Item 2')), Offset.zero);

    controller.jumpTo(2000.0);
    await tester.pump();
    expect(tester.getTopLeft(find.widgetWithText(SizedBox, 'Item 20')), Offset.zero);

    // The initialScrollOffset isn't used in this case, because the scrolloffset
    // can be restored.
    controller = ScrollController(initialScrollOffset: 25.0);
    await tester.pumpWidget(buildFrame(controller));
    expect(controller.offset, 2000.0);
    expect(tester.getTopLeft(find.widgetWithText(SizedBox, 'Item 20')), Offset.zero);

    // keepScrollOffset: false. The scroll offset is -not- restored
    // when the ListView is recreated with a new ScrollController and
    // the initialScrollOffset is used.

    controller = ScrollController(keepScrollOffset: false, initialScrollOffset: 100.0);
    await tester.pumpWidget(buildFrame(controller));
    expect(controller.offset, 100.0);
    expect(tester.getTopLeft(find.widgetWithText(SizedBox, 'Item 1')), Offset.zero);

  });

  testWidgets('isScrollingNotifier works with pointer scroll', (WidgetTester tester) async {
    Widget buildFrame(ScrollController controller) {
      return Directionality(
        textDirection: TextDirection.ltr,
        child: ListView(
          controller: controller,
          children: List<Widget>.generate(50, (int index) {
            return SizedBox(height: 100.0, child: Text('Item $index'));
          }).toList(),
        ),
      );
    }

    bool isScrolling = false;
    final ScrollController controller = ScrollController();
    controller.addListener((){
      isScrolling = controller.position.isScrollingNotifier.value;
    });
    await tester.pumpWidget(buildFrame(controller));
    final Offset scrollEventLocation = tester.getCenter(find.byType(ListView));
    final TestPointer testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
    // Create a hover event so that |testPointer| has a location when generating the scroll.
    testPointer.hover(scrollEventLocation);
    await tester.sendEventToBinding(testPointer.scroll(const Offset(0.0, 300.0)));
    // When the listener was notified, the value of the isScrollingNotifier
    // should have been true
    expect(isScrolling, isTrue);
  });
}
