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

class ExpandingBox extends StatefulWidget {
  const ExpandingBox({ Key? key, required this.collapsedSize, required this.expandedSize }) : super(key: key);

  final double collapsedSize;
  final double expandedSize;

  @override
  State<ExpandingBox> createState() => _ExpandingBoxState();
}

class _ExpandingBoxState extends State<ExpandingBox> with AutomaticKeepAliveClientMixin<ExpandingBox> {
  late double _height;

  @override
  void initState() {
    super.initState();
    _height = widget.collapsedSize;
  }

  void toggleSize() {
    setState(() {
      _height = _height == widget.collapsedSize ? widget.expandedSize : widget.collapsedSize;
    });
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Container(
      height: _height,
      color: Colors.green,
      child: Align(
        alignment: Alignment.bottomCenter,
        child: TextButton(
          onPressed: toggleSize,
          child: const Text('Collapse'),
        ),
      ),
    );
  }

  @override
  bool get wantKeepAlive => true;
}

void main() {
  testWidgets('shrink listview', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
      home: ListView.builder(
        itemBuilder: (BuildContext context, int index) => index == 0
              ? const ExpandingBox(collapsedSize: 400, expandedSize: 1200)
              : Container(height: 300, color: Colors.red),
        itemCount: 2,
      ),
    ));

    final ScrollPosition position = tester.state<ScrollableState>(find.byType(Scrollable)).position;
    expect(position.activity, isInstanceOf<IdleScrollActivity>());
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 100.0);
    expect(position.pixels, 0.0);
    await tester.tap(find.byType(TextButton));
    await tester.pump();

    final TestGesture drag1 = await tester.startGesture(const Offset(10.0, 500.0));
    await tester.pump();
    await drag1.moveTo(const Offset(10.0, 0.0));
    await tester.pump();
    await drag1.up();
    await tester.pump();
    expect(position.pixels, moreOrLessEquals(500.0));
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 900.0);

    final TestGesture drag2 = await tester.startGesture(const Offset(10.0, 500.0));
    await tester.pump();
    await drag2.moveTo(const Offset(10.0, 100.0));
    await tester.pump();
    await drag2.up();
    await tester.pump();
    expect(position.maxScrollExtent, 900.0);
    expect(position.pixels, moreOrLessEquals(900.0));

    await tester.pump();
    await tester.tap(find.byType(TextButton));
    await tester.pump();
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 100.0);
    expect(position.pixels, 100.0);
  });

  testWidgets('shrink listview while dragging', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
      home: ListView.builder(
        itemBuilder: (BuildContext context, int index) => index == 0
              ? const ExpandingBox(collapsedSize: 400, expandedSize: 1200)
              : Container(height: 300, color: Colors.red),
        itemCount: 2,
      ),
    ));

    final ScrollPosition position = tester.state<ScrollableState>(find.byType(Scrollable)).position;
    expect(position.activity, isInstanceOf<IdleScrollActivity>());
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 100.0);
    expect(position.pixels, 0.0);
    await tester.tap(find.byType(TextButton));
    await tester.pump(); // start button animation
    await tester.pump(const Duration(seconds: 1)); // finish button animation
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 1800.0);
    expect(position.pixels, 0.0);

    final TestGesture drag1 = await tester.startGesture(const Offset(10.0, 500.0));
    expect(await tester.pumpAndSettle(), 1); // Nothing to animate
    await drag1.moveTo(const Offset(10.0, 0.0));
    expect(await tester.pumpAndSettle(), 2); // Nothing to animate, only one semantics update
    await drag1.up();
    expect(await tester.pumpAndSettle(), 1); // Nothing to animate
    expect(position.pixels, moreOrLessEquals(500.0));
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 900.0);

    final TestGesture drag2 = await tester.startGesture(const Offset(10.0, 500.0));
    expect(await tester.pumpAndSettle(), 1); // Nothing to animate
    await drag2.moveTo(const Offset(10.0, 100.0));
    expect(await tester.pumpAndSettle(), 2); // Nothing to animate, only one semantics update
    expect(position.maxScrollExtent, 900.0);
    expect(position.pixels, lessThanOrEqualTo(900.0));
    expect(position.activity, isInstanceOf<DragScrollActivity>());

    final _ExpandingBoxState expandingBoxState = tester.state<_ExpandingBoxState>(find.byType(ExpandingBox));
    expandingBoxState.toggleSize();
    expect(await tester.pumpAndSettle(), 2); // Nothing to animate, only one semantics update
    expect(position.activity, isInstanceOf<DragScrollActivity>());
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 100.0);
    expect(position.pixels, 100.0);

    await drag2.moveTo(const Offset(10.0, 150.0));
    await drag2.up();
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 100.0);
    expect(position.pixels, 50.0);
    expect(await tester.pumpAndSettle(), 2); // Nothing to animate, only one semantics update
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 100.0);
    expect(position.pixels, 50.0);
  });

  testWidgets('shrink listview while ballistic', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
      home: GestureDetector(
        onTap: () { assert(false); },
        child: ListView.builder(
          physics: const RangeMaintainingScrollPhysics(parent: BouncingScrollPhysics()),
          itemBuilder: (BuildContext context, int index) => index == 0
                ? const ExpandingBox(collapsedSize: 400, expandedSize: 1200)
                : Container(height: 300, color: Colors.red),
          itemCount: 2,
        ),
      ),
    ));

    final _ExpandingBoxState expandingBoxState = tester.state<_ExpandingBoxState>(find.byType(ExpandingBox));
    expandingBoxState.toggleSize();

    final ScrollPosition position = tester.state<ScrollableState>(find.byType(Scrollable)).position;
    expect(position.activity, isInstanceOf<IdleScrollActivity>());
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 100.0);
    expect(position.pixels, 0.0);
    await tester.pump();
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 1800.0);
    expect(position.pixels, 0.0);

    final TestGesture drag1 = await tester.startGesture(const Offset(10.0, 10.0));
    await tester.pump();
    expect(position.activity, isInstanceOf<HoldScrollActivity>());
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 1800.0);
    expect(position.pixels, 0.0);
    await drag1.moveTo(const Offset(10.0, 50.0)); // to get past the slop and trigger the drag
    await drag1.moveTo(const Offset(10.0, 550.0));
    expect(position.pixels, -500.0);
    await tester.pump();
    expect(position.activity, isInstanceOf<DragScrollActivity>());
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 1800.0);
    expect(position.pixels, -500.0);
    await drag1.up();
    await tester.pump();
    expect(position.activity, isInstanceOf<BallisticScrollActivity>());
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 1800.0);
    expect(position.pixels, -500.0);

    expandingBoxState.toggleSize();
    await tester.pump(); // apply physics without moving clock forward
    expect(position.activity, isInstanceOf<BallisticScrollActivity>());
    // TODO(ianh): Determine why the maxScrollOffset is 200.0 here instead of 100.0 or double.infinity.
    // expect(position.minScrollExtent, 0.0);
    // expect(position.maxScrollExtent, 100.0);
    expect(position.pixels, -500.0);

    await tester.pumpAndSettle(); // ignoring the exact effects of the animation
    expect(position.activity, isInstanceOf<IdleScrollActivity>());
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, 100.0);
    expect(position.pixels, 0.0);
  });

  testWidgets('expanding page views', (WidgetTester tester) async {
    await tester.pumpWidget(const Padding(padding: EdgeInsets.only(right: 200.0), child: TabBarDemo()));
    await tester.tap(find.text('bike'));
    await tester.pump();
    await tester.pump(const Duration(seconds: 1));
    final Rect bike1 = tester.getRect(find.byIcon(Icons.directions_bike));
    await tester.pumpWidget(const Padding(padding: EdgeInsets.zero, child: TabBarDemo()));
    final Rect bike2 = tester.getRect(find.byIcon(Icons.directions_bike));
    expect(bike2.center, bike1.shift(const Offset(100.0, 0.0)).center);
  });

  testWidgets('changing the size of the viewport when overscrolled', (WidgetTester tester) async {
    Widget build(double height) {
      return Directionality(
        textDirection: TextDirection.rtl,
        child: ScrollConfiguration(
          behavior: const RangeMaintainingTestScrollBehavior(),
          child: Align(
            alignment: Alignment.topLeft,
            child: SizedBox(
              height: height,
              width: 100.0,
              child: ListView(
                children: const <Widget>[SizedBox(height: 100.0, child: Placeholder())],
              ),
            ),
          ),
        ),
      );
    }
    await tester.pumpWidget(build(200.0));
    // to verify that changing the size of the viewport while you are overdragged does not change the
    // scroll position, we must ensure that:
    // - velocity is zero
    // - scroll extents have changed
    // - position does not change at the same time
    // - old position is out of old range AND new range
    await tester.drag(find.byType(Placeholder), const Offset(0.0, 100.0), touchSlopY: 0.0, warnIfMissed: false); // it'll hit the scrollable
    await tester.pump();
    final Rect oldPosition = tester.getRect(find.byType(Placeholder));
    await tester.pumpWidget(build(220.0));
    final Rect newPosition = tester.getRect(find.byType(Placeholder));
    expect(oldPosition, newPosition);
  });

  testWidgets('inserting and removing an item when overscrolled', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/62890

    const double itemExtent = 100.0;
    final UniqueKey key = UniqueKey();
    final Finder finder = find.byKey(key);
    Widget build({required bool twoItems}) {
      return Directionality(
        textDirection: TextDirection.rtl,
        child: ScrollConfiguration(
          behavior: const RangeMaintainingTestScrollBehavior(),
          child: Align(
            child: SizedBox(
              width: 100.0,
              height: 100.0,
              child: ListView(
                children: <Widget>[
                  SizedBox(height: itemExtent, child: Placeholder(key: key)),
                  if (twoItems)
                    const SizedBox(height: itemExtent, child: Placeholder()),
                ],
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(build(twoItems: false));
    final ScrollPosition position = tester.state<ScrollableState>(find.byType(Scrollable)).position;

    // overscroll bottom
    final TestGesture drag1 = await tester.startGesture(tester.getCenter(finder));
    await tester.pump();
    await drag1.moveBy(const Offset(0.0, -50.0));
    await tester.pump();

    final double oldOverscroll1 = position.pixels - position.maxScrollExtent;
    final Rect oldPosition1 = tester.getRect(finder);
    await tester.pumpWidget(build(twoItems: true));
    // verify inserting new item didn't change the position of the first one
    expect(oldPosition1, tester.getRect(finder));
    // verify the overscroll changed by the size of the added item
    final double newOverscroll1 = position.pixels - position.maxScrollExtent;
    expect(oldOverscroll1, isPositive);
    expect(newOverscroll1, isNegative);
    expect(newOverscroll1, oldOverscroll1 - itemExtent);

    await drag1.up();

    // verify there's no ballistic animation, because we weren't overscrolled
    expect(await tester.pumpAndSettle(), 1);

    // overscroll bottom
    final TestGesture drag2 = await tester.startGesture(tester.getCenter(finder));
    await tester.pump();
    await drag2.moveBy(const Offset(0.0, -100.0));
    await tester.pump();

    final double oldOverscroll2 = position.pixels - position.maxScrollExtent;
    // should find nothing because item is not visible
    expect(finder, findsNothing);
    await tester.pumpWidget(build(twoItems: false));
    // verify removing an item changed the position of the first one, because prior it was not visible
    expect(oldPosition1, tester.getRect(finder));
    // verify the overscroll was maintained
    final double newOverscroll2 = position.pixels - position.maxScrollExtent;
    expect(oldOverscroll2, isPositive);
    expect(oldOverscroll2, newOverscroll2);

    await drag2.up();

    // verify there's a ballistic animation from overscroll
    expect(await tester.pumpAndSettle(), 9);
  });
}

class TabBarDemo extends StatelessWidget {
  const TabBarDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            bottom: const TabBar(
              tabs: <Widget>[
                Tab(text: 'car'),
                Tab(text: 'transit'),
                Tab(text: 'bike'),
              ],
            ),
            title: const Text('Tabs Demo'),
          ),
          body: const TabBarView(
            children: <Widget>[
              Icon(Icons.directions_car),
              Icon(Icons.directions_transit),
              Icon(Icons.directions_bike),
            ],
          ),
        ),
      ),
    );
  }
}

class RangeMaintainingTestScrollBehavior extends ScrollBehavior {
  const RangeMaintainingTestScrollBehavior();

  @override
  TargetPlatform getPlatform(BuildContext context) => throw 'should not be called';

  @override
  Widget buildOverscrollIndicator(BuildContext context, Widget child, ScrollableDetails details) {
    return child;
  }

  @override
  Widget buildScrollbar(BuildContext context, Widget child, ScrollableDetails details) {
    return child;
  }

  @override
  GestureVelocityTrackerBuilder velocityTrackerBuilder(BuildContext context) {
    return (PointerEvent event) => VelocityTracker.withKind(event.kind);
  }

  @override
  ScrollPhysics getScrollPhysics(BuildContext context) {
    return const BouncingScrollPhysics(parent: RangeMaintainingScrollPhysics());
  }
}
