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

late GestureVelocityTrackerBuilder lastCreatedBuilder;
class TestScrollBehavior extends ScrollBehavior {
  const TestScrollBehavior(this.flag);

  final bool flag;

  @override
  ScrollPhysics getScrollPhysics(BuildContext context) {
    return flag
      ? const ClampingScrollPhysics()
      : const BouncingScrollPhysics();
  }

  @override
  bool shouldNotify(TestScrollBehavior old) => flag != old.flag;

  @override
  GestureVelocityTrackerBuilder velocityTrackerBuilder(BuildContext context) {
      lastCreatedBuilder = flag
        ? (PointerEvent ev) => VelocityTracker.withKind(ev.kind)
        : (PointerEvent ev) => IOSScrollViewFlingVelocityTracker(ev.kind);
      return lastCreatedBuilder;
  }
}

void main() {
  testWidgets('Inherited ScrollConfiguration changed', (WidgetTester tester) async {
    final GlobalKey key = GlobalKey(debugLabel: 'scrollable');
    TestScrollBehavior? behavior;
    late ScrollPositionWithSingleContext position;

    final Widget scrollView = SingleChildScrollView(
      key: key,
      child: Builder(
        builder: (BuildContext context) {
          behavior = ScrollConfiguration.of(context) as TestScrollBehavior;
          position = Scrollable.of(context)!.position as ScrollPositionWithSingleContext;
          return Container(height: 1000.0);
        },
      ),
    );

    await tester.pumpWidget(
      ScrollConfiguration(
        behavior: const TestScrollBehavior(true),
        child: scrollView,
      ),
    );

    expect(behavior, isNotNull);
    expect(behavior!.flag, isTrue);
    expect(position.physics, isA<ClampingScrollPhysics>());
    expect(lastCreatedBuilder(const PointerDownEvent()), isA<VelocityTracker>());
    ScrollMetrics metrics = position.copyWith();
    expect(metrics.extentAfter, equals(400.0));
    expect(metrics.viewportDimension, equals(600.0));

    // Same Scrollable, different ScrollConfiguration
    await tester.pumpWidget(
      ScrollConfiguration(
        behavior: const TestScrollBehavior(false),
        child: scrollView,
      ),
    );

    expect(behavior, isNotNull);
    expect(behavior!.flag, isFalse);
    expect(position.physics, isA<BouncingScrollPhysics>());
    expect(lastCreatedBuilder(const PointerDownEvent()), isA<IOSScrollViewFlingVelocityTracker>());
    // Regression test for https://github.com/flutter/flutter/issues/5856
    metrics = position.copyWith();
    expect(metrics.extentAfter, equals(400.0));
    expect(metrics.viewportDimension, equals(600.0));
  });

  testWidgets('ScrollBehavior default android overscroll indicator', (WidgetTester tester) async {
    await tester.pumpWidget(Directionality(
        textDirection: TextDirection.ltr,
        child: ScrollConfiguration(
          behavior: const ScrollBehavior(),
          child: ListView(
            children: const <Widget>[
              SizedBox(
                height: 1000.0,
                width: 1000.0,
                child: Text('Test'),
              )
            ]
          )
        ),
    ));

    expect(find.byType(StretchingOverscrollIndicator), findsNothing);
    expect(find.byType(GlowingOverscrollIndicator), findsOneWidget);
  }, variant: TargetPlatformVariant.only(TargetPlatform.android));

  testWidgets('ScrollBehavior stretch android overscroll indicator', (WidgetTester tester) async {
    await tester.pumpWidget(Directionality(
      textDirection: TextDirection.ltr,
      child: MediaQuery(
        data: const MediaQueryData(size: Size(800, 600)),
        child: ScrollConfiguration(
            behavior: const ScrollBehavior(androidOverscrollIndicator: AndroidOverscrollIndicator.stretch),
            child: ListView(
                children: const <Widget>[
                  SizedBox(
                    height: 1000.0,
                    width: 1000.0,
                    child: Text('Test'),
                  )
                ]
            )
        ),
      ),
    ));

    expect(find.byType(StretchingOverscrollIndicator), findsOneWidget);
    expect(find.byType(GlowingOverscrollIndicator), findsNothing);
  }, variant: TargetPlatformVariant.only(TargetPlatform.android));

  group('ScrollBehavior configuration is maintained over multiple copies', () {
    testWidgets('dragDevices', (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/91673
      const ScrollBehavior defaultBehavior = ScrollBehavior();
      expect(defaultBehavior.dragDevices, <PointerDeviceKind>{
        PointerDeviceKind.touch,
        PointerDeviceKind.stylus,
        PointerDeviceKind.invertedStylus,
      });

      // Use copyWith to modify drag devices
      final ScrollBehavior onceCopiedBehavior = defaultBehavior.copyWith(
        dragDevices: PointerDeviceKind.values.toSet(),
      );
      expect(onceCopiedBehavior.dragDevices, PointerDeviceKind.values.toSet());

      // Copy again. The previously modified drag devices should carry over.
      final ScrollBehavior twiceCopiedBehavior = onceCopiedBehavior.copyWith();
      expect(twiceCopiedBehavior.dragDevices, PointerDeviceKind.values.toSet());
    });

    testWidgets('androidOverscrollIndicator', (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/91673
      const ScrollBehavior defaultBehavior = ScrollBehavior();
      expect(defaultBehavior.androidOverscrollIndicator, AndroidOverscrollIndicator.glow);

      // Use copyWith to modify androidOverscrollIndicator
      final ScrollBehavior onceCopiedBehavior = defaultBehavior.copyWith(
        androidOverscrollIndicator: AndroidOverscrollIndicator.stretch,
      );
      expect(onceCopiedBehavior.androidOverscrollIndicator, AndroidOverscrollIndicator.stretch);

      // Copy again. The previously modified value should carry over.
      final ScrollBehavior twiceCopiedBehavior = onceCopiedBehavior.copyWith();
      expect(twiceCopiedBehavior.androidOverscrollIndicator, AndroidOverscrollIndicator.stretch);
    });

    testWidgets('physics', (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/91673
      late ScrollPhysics defaultPhysics;
      late ScrollPhysics onceCopiedPhysics;
      late ScrollPhysics twiceCopiedPhysics;

      await tester.pumpWidget(ScrollConfiguration(
        // Default ScrollBehavior
        behavior: const ScrollBehavior(),
        child: Builder(
          builder: (BuildContext context) {
            final ScrollBehavior defaultBehavior = ScrollConfiguration.of(context);
            // Copy once to change physics
            defaultPhysics = defaultBehavior.getScrollPhysics(context);
            return ScrollConfiguration(
              behavior: defaultBehavior.copyWith(physics: const BouncingScrollPhysics()),
              child: Builder(
                builder: (BuildContext context) {
                  final ScrollBehavior onceCopiedBehavior = ScrollConfiguration.of(context);
                  onceCopiedPhysics = onceCopiedBehavior.getScrollPhysics(context);
                  return ScrollConfiguration(
                    // Copy again, physics should follow
                    behavior: onceCopiedBehavior.copyWith(),
                    child: Builder(
                      builder: (BuildContext context) {
                        twiceCopiedPhysics = ScrollConfiguration.of(context).getScrollPhysics(context);
                        return SingleChildScrollView(child: Container(height: 1000));
                      }
                    )
                  );
                }
              )
            );
          }
        ),
      ));

      expect(defaultPhysics, const ClampingScrollPhysics(parent: RangeMaintainingScrollPhysics()));
      expect(onceCopiedPhysics, const BouncingScrollPhysics());
      expect(twiceCopiedPhysics, const BouncingScrollPhysics());
    });

    testWidgets('platform', (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/91673
      late TargetPlatform defaultPlatform;
      late TargetPlatform onceCopiedPlatform;
      late TargetPlatform twiceCopiedPlatform;

      await tester.pumpWidget(ScrollConfiguration(
        // Default ScrollBehavior
        behavior: const ScrollBehavior(),
        child: Builder(
            builder: (BuildContext context) {
              final ScrollBehavior defaultBehavior = ScrollConfiguration.of(context);
              // Copy once to change physics
              defaultPlatform = defaultBehavior.getPlatform(context);
              return ScrollConfiguration(
                  behavior: defaultBehavior.copyWith(platform: TargetPlatform.fuchsia),
                  child: Builder(
                      builder: (BuildContext context) {
                        final ScrollBehavior onceCopiedBehavior = ScrollConfiguration.of(context);
                        onceCopiedPlatform = onceCopiedBehavior.getPlatform(context);
                        return ScrollConfiguration(
                          // Copy again, physics should follow
                            behavior: onceCopiedBehavior.copyWith(),
                            child: Builder(
                                builder: (BuildContext context) {
                                  twiceCopiedPlatform = ScrollConfiguration.of(context).getPlatform(context);
                                  return SingleChildScrollView(child: Container(height: 1000));
                                }
                            )
                        );
                      }
                  )
              );
            }
        ),
      ));

      expect(defaultPlatform, TargetPlatform.android);
      expect(onceCopiedPlatform, TargetPlatform.fuchsia);
      expect(twiceCopiedPlatform, TargetPlatform.fuchsia);
    });

    Widget wrap(ScrollBehavior behavior) {
      return Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: const MediaQueryData(size: Size(500, 500)),
            child: ScrollConfiguration(
                behavior: behavior,
                child: Builder(
                    builder: (BuildContext context) => SingleChildScrollView(child: Container(height: 1000))
                )
            ),
          )
      );
    }

    testWidgets('scrollbar', (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/91673
      const  ScrollBehavior defaultBehavior = ScrollBehavior();
      await tester.pumpWidget(wrap(defaultBehavior));
      // Default adds a scrollbar
      expect(find.byType(RawScrollbar), findsOneWidget);
      final ScrollBehavior onceCopiedBehavior = defaultBehavior.copyWith(scrollbars: false);

      await tester.pumpWidget(wrap(onceCopiedBehavior));
      // Copy does not add scrollbar
      expect(find.byType(RawScrollbar), findsNothing);
      final ScrollBehavior twiceCopiedBehavior = onceCopiedBehavior.copyWith();

      await tester.pumpWidget(wrap(twiceCopiedBehavior));
      // Second copy maintains scrollbar setting
      expect(find.byType(RawScrollbar), findsNothing);

      // For default scrollbars
    }, variant: TargetPlatformVariant.desktop());

    testWidgets('overscroll', (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/91673
      const  ScrollBehavior defaultBehavior = ScrollBehavior();
      await tester.pumpWidget(wrap(defaultBehavior));
      // Default adds a glowing overscroll indicator
      expect(find.byType(GlowingOverscrollIndicator), findsOneWidget);
      final ScrollBehavior onceCopiedBehavior = defaultBehavior.copyWith(overscroll: false);

      await tester.pumpWidget(wrap(onceCopiedBehavior));
      // Copy does not add indicator
      expect(find.byType(GlowingOverscrollIndicator), findsNothing);
      final ScrollBehavior twiceCopiedBehavior = onceCopiedBehavior.copyWith();

      await tester.pumpWidget(wrap(twiceCopiedBehavior));
      // Second copy maintains overscroll setting
      expect(find.byType(GlowingOverscrollIndicator), findsNothing);

      // For default glowing indicator
    }, variant: TargetPlatformVariant.only(TargetPlatform.android));
  });
}
