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

// The const represents the starting position of the scrollbar thumb for
// the below tests. The thumb is 90 pixels long, and 8 pixels wide, with a 2
// pixel margin to the right edge of the viewport.
const Rect _kMaterialDesignInitialThumbRect = Rect.fromLTRB(790.0, 0.0, 798.0, 90.0);
const Radius _kDefaultThumbRadius = Radius.circular(8.0);
const Color _kDefaultIdleThumbColor = Color(0x1a000000);
const Color _kDefaultDragThumbColor = Color(0x99000000);

void main() {
  test('ScrollbarThemeData copyWith, ==, hashCode basics', () {
    expect(const ScrollbarThemeData(), const ScrollbarThemeData().copyWith());
    expect(const ScrollbarThemeData().hashCode, const ScrollbarThemeData().copyWith().hashCode);
  });

  test('ScrollbarThemeData lerp special cases', () {
    expect(ScrollbarThemeData.lerp(null, null, 0), const ScrollbarThemeData());
    const ScrollbarThemeData data = ScrollbarThemeData();
    expect(identical(ScrollbarThemeData.lerp(data, data, 0.5), data), true);
  });

  testWidgets('Passing no ScrollbarTheme returns defaults', (WidgetTester tester) async {
    final ScrollController scrollController = ScrollController();
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(
          useMaterial3: false,
          scrollbarTheme: ScrollbarThemeData(
            trackVisibility: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
              if (states.contains(MaterialState.hovered)) {
                return true;
              }
              return false;
            })
          )
        ),
        home: ScrollConfiguration(
          behavior: const NoScrollbarBehavior(),
          child: Scrollbar(
            thumbVisibility: true,
            controller: scrollController,
            child: SingleChildScrollView(
              controller: scrollController,
              child: const SizedBox(width: 4000.0, height: 4000.0),
            ),
          ),
        ),
      ),
    );
    await tester.pumpAndSettle();
    // Idle scrollbar behavior
    expect(
      find.byType(Scrollbar),
      paints..rrect(
        rrect: RRect.fromRectAndRadius(
          _kMaterialDesignInitialThumbRect,
          _kDefaultThumbRadius,
        ),
        color: _kDefaultIdleThumbColor,
      ),
    );

    // Drag scrollbar behavior
    const double scrollAmount = 10.0;
    final TestGesture dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0));
    await tester.pumpAndSettle();

    expect(
      find.byType(Scrollbar),
      paints..rrect(
        rrect: RRect.fromRectAndRadius(
          _kMaterialDesignInitialThumbRect,
          _kDefaultThumbRadius,
        ),
        // Drag color
        color: _kDefaultDragThumbColor,
      ),
    );

    await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount));
    await tester.pumpAndSettle();
    await dragScrollbarGesture.up();
    await tester.pumpAndSettle();

    // Hover scrollbar behavior
    final TestGesture gesture = await tester.createGesture(kind: ui.PointerDeviceKind.mouse);
    await gesture.addPointer();
    await gesture.moveTo(const Offset(794.0, 5.0));
    await tester.pumpAndSettle();

    expect(
      find.byType(Scrollbar),
      paints
        ..rect(
          rect: const Rect.fromLTRB(784.0, 0.0, 800.0, 600.0),
          color: const Color(0x08000000),
        )
        ..line(
          p1: const Offset(784.0, 0.0),
          p2: const Offset(784.0, 600.0),
          strokeWidth: 1.0,
          color: const Color(0x1a000000),
        )
        ..rrect(
          rrect: RRect.fromRectAndRadius(
            // Scrollbar thumb is larger
            const Rect.fromLTRB(786.0, 10.0, 798.0, 100.0),
            _kDefaultThumbRadius,
          ),
          // Hover color
          color: const Color(0x80000000),
        ),
    );

    scrollController.dispose();
  }, variant: const TargetPlatformVariant(<TargetPlatform>{
       TargetPlatform.linux,
       TargetPlatform.macOS,
       TargetPlatform.windows,
       TargetPlatform.fuchsia,
    }),
  );

  testWidgets('Scrollbar uses values from ScrollbarTheme', (WidgetTester tester) async {
    final ScrollbarThemeData scrollbarTheme = _scrollbarTheme();
    final ScrollController scrollController = ScrollController();
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(
        scrollbarTheme: scrollbarTheme,
      ),
      home: ScrollConfiguration(
        behavior: const NoScrollbarBehavior(),
        child: Scrollbar(
          thumbVisibility: true,
          controller: scrollController,
          child: SingleChildScrollView(
            controller: scrollController,
            child: const SizedBox(width: 4000.0, height: 4000.0),
          ),
        ),
      ),
    ));
    await tester.pumpAndSettle();
    // Idle scrollbar behavior
    expect(
      find.byType(Scrollbar),
      paints..rrect(
        rrect: RRect.fromRectAndRadius(
          const Rect.fromLTRB(785.0, 10.0, 795.0, 97.0),
          const Radius.circular(6.0),
        ),
        color: const Color(0xff4caf50),
      ),
    );

    // Drag scrollbar behavior
    const double scrollAmount = 10.0;
    final TestGesture dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0));
    await tester.pumpAndSettle();

    expect(
      find.byType(Scrollbar),
      paints..rrect(
        rrect: RRect.fromRectAndRadius(
          const Rect.fromLTRB(785.0, 10.0, 795.0, 97.0),
          const Radius.circular(6.0),
        ),
        // Drag color
        color: const Color(0xfff44336),
      ),
    );

    await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount));
    await tester.pumpAndSettle();
    await dragScrollbarGesture.up();
    await tester.pumpAndSettle();

    // Hover scrollbar behavior
    final TestGesture gesture = await tester.createGesture(kind: ui.PointerDeviceKind.mouse);
    await gesture.addPointer();
    await gesture.moveTo(const Offset(794.0, 15.0));
    await tester.pumpAndSettle();

    expect(
      find.byType(Scrollbar),
      paints
        ..rect(
          rect: const Rect.fromLTRB(770.0, 0.0, 800.0, 600.0),
          color: const Color(0xff000000),
        )
        ..line(
          p1: const Offset(770.0, 00.0),
          p2: const Offset(770.0, 600.0),
          strokeWidth: 1.0,
          color: const Color(0xffffeb3b),
        )
        ..rrect(
          rrect: RRect.fromRectAndRadius(
            // Scrollbar thumb is larger
            const Rect.fromLTRB(775.0, 20.0, 795.0, 107.0),
            const Radius.circular(6.0),
          ),
          // Hover color
          color: const Color(0xff2196f3),
        ),
    );

    scrollController.dispose();
  }, variant: const TargetPlatformVariant(<TargetPlatform>{
       TargetPlatform.linux,
       TargetPlatform.macOS,
       TargetPlatform.windows,
       TargetPlatform.fuchsia,
    }),
  );

  testWidgets(
    'Scrollbar uses values from ScrollbarTheme if exists instead of values from Theme',
    (WidgetTester tester) async {
      final ScrollbarThemeData scrollbarTheme = _scrollbarTheme();
      final ScrollController scrollController = ScrollController();
      await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData(
            scrollbarTheme: scrollbarTheme,
          ),
          home: ScrollConfiguration(
            behavior: const NoScrollbarBehavior(),
            child: ScrollbarTheme(
              data: _scrollbarTheme().copyWith(
                thumbColor: MaterialStateProperty.all(const Color(0xFF000000)),
              ),
              child: Scrollbar(
                thumbVisibility: true,
                controller: scrollController,
                child: SingleChildScrollView(
                  controller: scrollController,
                  child: const SizedBox(width: 4000.0, height: 4000.0),
                ),
              ),
            ),
          ),
        ),
      );
      await tester.pumpAndSettle();
      // Idle scrollbar behavior
      expect(
        find.byType(Scrollbar),
        paints
          ..rrect(
            rrect: RRect.fromRectAndRadius(
              const Rect.fromLTRB(785.0, 10.0, 795.0, 97.0),
              const Radius.circular(6.0),
            ),
            color: const Color(0xFF000000),
          ),
      );

      scrollController.dispose();
    },
  );

  testWidgets('ScrollbarTheme can disable gestures', (WidgetTester tester) async {
    final ScrollController scrollController = ScrollController();
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(useMaterial3: false, scrollbarTheme: const ScrollbarThemeData(interactive: false)),
      home: Scrollbar(
        thumbVisibility: true,
        controller: scrollController,
        child: SingleChildScrollView(
          controller: scrollController,
          child: const SizedBox(width: 4000.0, height: 4000.0),
        ),
      ),
    ));
    await tester.pumpAndSettle();
    // Idle scrollbar behavior
    expect(
      find.byType(Scrollbar),
      paints..rrect(
        rrect: RRect.fromRectAndRadius(
          _kMaterialDesignInitialThumbRect,
          _kDefaultThumbRadius,
        ),
        color: _kDefaultIdleThumbColor,
      ),
    );

    // Try to drag scrollbar.
    const double scrollAmount = 10.0;
    final TestGesture dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0));
    await tester.pumpAndSettle();
    await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount));
    await tester.pumpAndSettle();
    await dragScrollbarGesture.up();
    await tester.pumpAndSettle();
    // Expect no change
    expect(
      find.byType(Scrollbar),
      paints..rrect(
        rrect: RRect.fromRectAndRadius(
          _kMaterialDesignInitialThumbRect,
          _kDefaultThumbRadius,
        ),
        color: _kDefaultIdleThumbColor,
      ),
    );

    scrollController.dispose();
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.fuchsia }));

  testWidgets('Scrollbar.interactive takes priority over ScrollbarTheme', (WidgetTester tester) async {
    final ScrollController scrollController = ScrollController();
    await tester.pumpWidget(MaterialApp(
      theme: ThemeData(useMaterial3: false, scrollbarTheme: const ScrollbarThemeData(interactive: false)),
      home: Scrollbar(
        interactive: true,
        thumbVisibility: true,
        controller: scrollController,
        child: SingleChildScrollView(
          controller: scrollController,
          child: const SizedBox(width: 4000.0, height: 4000.0),
        ),
      ),
    ));
    await tester.pumpAndSettle();
    // Idle scrollbar behavior
    expect(
      find.byType(Scrollbar),
      paints..rrect(
        rrect: RRect.fromRectAndRadius(
          _kMaterialDesignInitialThumbRect,
          _kDefaultThumbRadius,
        ),
        color: _kDefaultIdleThumbColor,
      ),
    );

    // Drag scrollbar.
    const double scrollAmount = 10.0;
    final TestGesture dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0));
    await tester.pumpAndSettle();
    await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount));
    await tester.pumpAndSettle();
    await dragScrollbarGesture.up();
    await tester.pumpAndSettle();
    // Gestures handled by Scrollbar.
    expect(
      find.byType(Scrollbar),
      paints..rrect(
        rrect: RRect.fromRectAndRadius(
          const Rect.fromLTRB(790.0, 10.0, 798.0, 100.0),
          _kDefaultThumbRadius,
        ),
        color: _kDefaultIdleThumbColor,
      ),
    );

    scrollController.dispose();
  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.fuchsia }));

  testWidgets('Scrollbar widget properties take priority over theme', (WidgetTester tester) async {
    const double thickness = 4.0;
    const double edgeMargin = 2.0;
    const Radius radius = Radius.circular(3.0);
    final ScrollController scrollController = ScrollController();

    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(
          colorScheme: const ColorScheme.light(),
          scrollbarTheme: ScrollbarThemeData(
            trackVisibility: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
              if (states.contains(MaterialState.hovered)) {
                return true;
              }
              return false;
            })
          ),
        ),
        home: ScrollConfiguration(
          behavior: const NoScrollbarBehavior(),
          child: Scrollbar(
            thickness: thickness,
            thumbVisibility: true,
            radius: radius,
            controller: scrollController,
            child: SingleChildScrollView(
              controller: scrollController,
              child: const SizedBox(width: 4000.0, height: 4000.0),
            ),
          ),
        ),
      ),
    );

    await tester.pumpAndSettle();
    // Idle scrollbar behavior
    expect(
      find.byType(Scrollbar),
      paints..rrect(
        rrect: RRect.fromRectAndRadius(
          const Rect.fromLTRB(800 - thickness - edgeMargin, 0.0, 798.0, 90.0),
          const Radius.circular(3.0),
        ),
        color: _kDefaultIdleThumbColor,
      ),
    );

    // Drag scrollbar behavior.
    const double scrollAmount = 10.0;
    final TestGesture dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0));
    await tester.pumpAndSettle();

    expect(
      find.byType(Scrollbar),
      paints..rrect(
        rrect: RRect.fromRectAndRadius(
          const Rect.fromLTRB(800 - thickness - edgeMargin, 0.0, 798.0, 90.0),
          const Radius.circular(3.0),
        ),
        // Drag color
        color: _kDefaultDragThumbColor,
      ),
    );

    await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount));
    await tester.pumpAndSettle();
    await dragScrollbarGesture.up();
    await tester.pumpAndSettle();

    // Hover scrollbar behavior.
    final TestGesture gesture = await tester.createGesture(kind: ui.PointerDeviceKind.mouse);
    await gesture.addPointer();
    await gesture.moveTo(const Offset(794.0, 5.0));
    await tester.pumpAndSettle();

    expect(
      find.byType(Scrollbar),
      paints
        ..rect(
          rect: const Rect.fromLTRB(792.0, 0.0, 800.0, 600.0),
          color: const Color(0x08000000),
        )
        ..line(
          p1: const Offset(792.0, 0.0),
          p2: const Offset(792.0, 600.0),
          strokeWidth: 1.0,
          color: const Color(0x1a000000),
        )
        ..rrect(
          rrect: RRect.fromRectAndRadius(
            const Rect.fromLTRB(800 - thickness - edgeMargin, 10.0, 798.0, 100.0),
            const Radius.circular(3.0),
          ),
          // Hover color
          color: const Color(0x80000000),
        ),
    );

    scrollController.dispose();
  }, variant: const TargetPlatformVariant(<TargetPlatform>{
       TargetPlatform.linux,
       TargetPlatform.macOS,
       TargetPlatform.windows,
       TargetPlatform.fuchsia,
    }),
  );

  testWidgets('ThemeData colorScheme is used when no ScrollbarTheme is set', (WidgetTester tester) async {
    (ScrollController, Widget) buildFrame(ThemeData appTheme) {
      final ScrollController scrollController = ScrollController();
      final ThemeData theme = appTheme.copyWith(
        scrollbarTheme: ScrollbarThemeData(
          trackVisibility: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
            if (states.contains(MaterialState.hovered)) {
              return true;
            }
            return false;
          })
        ),
      );
      return (
          scrollController,
          MaterialApp(
            theme: theme,
            home: ScrollConfiguration(
              behavior: const NoScrollbarBehavior(),
              child: Scrollbar(
                thumbVisibility: true,
                controller: scrollController,
                child: SingleChildScrollView(
                  controller: scrollController,
                  child: const SizedBox(width: 4000.0, height: 4000.0),
                ),
              ),
            ),
          ),
        );
    }

    // Scrollbar defaults for light themes:
    // - coloring based on ColorScheme.onSurface
    final (ScrollController controller1, Widget frame1) = buildFrame(ThemeData(
      colorScheme: const ColorScheme.light(),
    ));
    await tester.pumpWidget(frame1);
    await tester.pumpAndSettle();
    // Idle scrollbar behavior
    expect(
      find.byType(Scrollbar),
      paints..rrect(
        rrect: RRect.fromRectAndRadius(
          _kMaterialDesignInitialThumbRect,
          _kDefaultThumbRadius,
        ),
        color: _kDefaultIdleThumbColor,
      ),
    );

    // Drag scrollbar behavior
    const double scrollAmount = 10.0;
    TestGesture dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0));
    await tester.pumpAndSettle();

    expect(
      find.byType(Scrollbar),
      paints..rrect(
        rrect: RRect.fromRectAndRadius(
          _kMaterialDesignInitialThumbRect,
          _kDefaultThumbRadius,
        ),
        // Drag color
        color: _kDefaultDragThumbColor,
      ),
    );

    await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount));
    await tester.pumpAndSettle();
    await dragScrollbarGesture.up();
    await tester.pumpAndSettle();

    // Hover scrollbar behavior
    final TestGesture hoverGesture = await tester.createGesture(kind: ui.PointerDeviceKind.mouse);
    await hoverGesture.addPointer();
    addTearDown(hoverGesture.removePointer);
    await hoverGesture.moveTo(const Offset(794.0, 5.0));
    await tester.pumpAndSettle();

    expect(
      find.byType(Scrollbar),
      paints
        ..rect(
          rect: const Rect.fromLTRB(784.0, 0.0, 800.0, 600.0),
          color: const Color(0x08000000),
        )
        ..line(
          p1: const Offset(784.0, 0.0),
          p2: const Offset(784.0, 600.0),
          strokeWidth: 1.0,
          color: const Color(0x1a000000),
        )
        ..rrect(
          rrect: RRect.fromRectAndRadius(
            // Scrollbar thumb is larger
            const Rect.fromLTRB(786.0, 10.0, 798.0, 100.0),
            _kDefaultThumbRadius,
          ),
          // Hover color
          color: const Color(0x80000000),
        ),
    );

    await hoverGesture.moveTo(Offset.zero);

    // Scrollbar defaults for dark themes:
    // - coloring slightly different based on ColorScheme.onSurface
    final (ScrollController controller2, Widget frame2) = buildFrame(ThemeData(
      colorScheme: const ColorScheme.dark(),
    ));
    await tester.pumpWidget(frame2);
    await tester.pumpAndSettle(); // Theme change animation

    // Idle scrollbar behavior
    expect(
      find.byType(Scrollbar),
      paints..rrect(
        rrect: RRect.fromRectAndRadius(
          const Rect.fromLTRB(790.0, 10.0, 798.0, 100.0),
          _kDefaultThumbRadius,
        ),
        color: const Color(0x4dffffff),
      ),
    );

    // Drag scrollbar behavior
    dragScrollbarGesture = await tester.startGesture(const Offset(797.0, 45.0));
    await tester.pumpAndSettle();

    expect(
      find.byType(Scrollbar),
      paints..rrect(
        rrect: RRect.fromRectAndRadius(
          const Rect.fromLTRB(790.0, 10.0, 798.0, 100.0),
          _kDefaultThumbRadius,
        ),
        // Drag color
        color: const Color(0xbfffffff),
      ),
    );

    await dragScrollbarGesture.moveBy(const Offset(0.0, scrollAmount));
    await tester.pumpAndSettle();
    await dragScrollbarGesture.up();
    await tester.pumpAndSettle();

    // Hover scrollbar behavior
    await hoverGesture.moveTo(const Offset(794.0, 5.0));
    await tester.pumpAndSettle();

    expect(
      find.byType(Scrollbar),
      paints
        ..rect(
          rect: const Rect.fromLTRB(784.0, 0.0, 800.0, 600.0),
          color: const Color(0x0dffffff),
        )
        ..line(
          p1: const Offset(784.0, 0.0),
          p2: const Offset(784.0, 600.0),
          strokeWidth: 1.0,
          color: const Color(0x40ffffff),
        )
        ..rrect(
          rrect: RRect.fromRectAndRadius(
            // Scrollbar thumb is larger
            const Rect.fromLTRB(786.0, 20.0, 798.0, 110.0),
            _kDefaultThumbRadius,
          ),
          // Hover color
          color: const Color(0xa6ffffff),
        ),
    );

    controller1.dispose();
    controller2.dispose();
  }, variant: const TargetPlatformVariant(<TargetPlatform>{
       TargetPlatform.linux,
       TargetPlatform.macOS,
       TargetPlatform.windows,
       TargetPlatform.fuchsia,
    }),
  );

  testWidgets('ScrollbarThemeData.trackVisibility test', (WidgetTester tester) async {
    final ScrollController scrollController = ScrollController();
    bool? getTrackVisibility(Set<MaterialState> states) {
      return true;
    }
    await tester.pumpWidget(
      MaterialApp(
        theme: ThemeData(useMaterial3: false).copyWith(
          scrollbarTheme: _scrollbarTheme(
            trackVisibility: MaterialStateProperty.resolveWith(getTrackVisibility),
          ),
        ),
        home: ScrollConfiguration(
          behavior: const NoScrollbarBehavior(),
          child: Scrollbar(
            thumbVisibility: true,
            controller: scrollController,
            child: SingleChildScrollView(
              controller: scrollController,
              child: const SizedBox(width: 4000.0, height: 4000.0),
            ),
          ),
        ),
      ),
    );
    await tester.pumpAndSettle();

    expect(
      find.byType(Scrollbar),
      paints
        ..rect(color: const Color(0x08000000))
        ..line(
          strokeWidth: 1.0,
          color: const Color(0x1a000000),
        )
        ..rrect(color: const Color(0xff4caf50)),
    );

    scrollController.dispose();
  }, variant: const TargetPlatformVariant(<TargetPlatform>{
    TargetPlatform.linux,
    TargetPlatform.macOS,
    TargetPlatform.windows,
    TargetPlatform.fuchsia,
  }),
  );

  testWidgets('Default ScrollbarTheme debugFillProperties', (WidgetTester tester) async {
    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
    const ScrollbarThemeData().debugFillProperties(builder);

    final List<String> description = builder.properties
      .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
      .map((DiagnosticsNode node) => node.toString())
      .toList();

    expect(description, <String>[]);
  });

  testWidgets('ScrollbarTheme implements debugFillProperties', (WidgetTester tester) async {
    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
    ScrollbarThemeData(
      thickness: MaterialStateProperty.resolveWith(_getThickness),
      thumbVisibility: MaterialStateProperty.resolveWith(_getThumbVisibility),
      radius: const Radius.circular(3.0),
      thumbColor: MaterialStateProperty.resolveWith(_getThumbColor),
      trackColor: MaterialStateProperty.resolveWith(_getTrackColor),
      trackBorderColor: MaterialStateProperty.resolveWith(_getTrackBorderColor),
      crossAxisMargin: 3.0,
      mainAxisMargin: 6.0,
      minThumbLength: 120.0,
    ).debugFillProperties(builder);

    final List<String> description = builder.properties
      .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
      .map((DiagnosticsNode node) => node.toString())
      .toList();

    expect(description, <String>[
      "thumbVisibility: Instance of '_WidgetStatePropertyWith<bool?>'",
      "thickness: Instance of '_WidgetStatePropertyWith<double?>'",
      'radius: Radius.circular(3.0)',
      "thumbColor: Instance of '_WidgetStatePropertyWith<Color?>'",
      "trackColor: Instance of '_WidgetStatePropertyWith<Color?>'",
      "trackBorderColor: Instance of '_WidgetStatePropertyWith<Color?>'",
      'crossAxisMargin: 3.0',
      'mainAxisMargin: 6.0',
      'minThumbLength: 120.0',
    ]);

    // On the web, Dart doubles and ints are backed by the same kind of object because
    // JavaScript does not support integers. So, the Dart double "4.0" is identical
    // to "4", which results in the web evaluating to the value "4" regardless of which
    // one is used. This results in a difference for doubles in debugFillProperties between
    // the web and the rest of Flutter's target platforms.
  }, skip: kIsWeb); // [intended]
}

class NoScrollbarBehavior extends ScrollBehavior {
  const NoScrollbarBehavior();

  @override
  Widget buildScrollbar(BuildContext context, Widget child, ScrollableDetails details) => child;
}

ScrollbarThemeData _scrollbarTheme({
  MaterialStateProperty<double?>? thickness,
  MaterialStateProperty<bool?>? trackVisibility,
  MaterialStateProperty<bool?>? thumbVisibility,
  Radius radius = const Radius.circular(6.0),
  MaterialStateProperty<Color?>? thumbColor,
  MaterialStateProperty<Color?>? trackColor,
  MaterialStateProperty<Color?>? trackBorderColor,
  double crossAxisMargin = 5.0,
  double mainAxisMargin = 10.0,
  double minThumbLength = 50.0,
}) {
  return ScrollbarThemeData(
    thickness: thickness ?? MaterialStateProperty.resolveWith(_getThickness),
    trackVisibility: trackVisibility ?? MaterialStateProperty.resolveWith((Set<MaterialState> states) {
      if (states.contains(MaterialState.hovered)) {
        return true;
      }
      return false;
    }),
    thumbVisibility: thumbVisibility,
    radius: radius,
    thumbColor: thumbColor ?? MaterialStateProperty.resolveWith(_getThumbColor),
    trackColor: trackColor ?? MaterialStateProperty.resolveWith(_getTrackColor),
    trackBorderColor: trackBorderColor ?? MaterialStateProperty.resolveWith(_getTrackBorderColor),
    crossAxisMargin: crossAxisMargin,
    mainAxisMargin: mainAxisMargin,
    minThumbLength: minThumbLength,
  );
}

double? _getThickness(Set<MaterialState> states) {
  if (states.contains(MaterialState.hovered)) {
    return 20.0;
  }
  return 10.0;
}

bool? _getThumbVisibility(Set<MaterialState> states) => true;

Color? _getThumbColor(Set<MaterialState> states) {
  if (states.contains(MaterialState.dragged)) {
    return Colors.red;
  }
  if (states.contains(MaterialState.hovered)) {
    return Colors.blue;
  }
  return Colors.green;
}

Color? _getTrackColor(Set<MaterialState> states) {
  if (states.contains(MaterialState.hovered)) {
    return Colors.black;
  }
  return null;
}

Color? _getTrackBorderColor(Set<MaterialState> states) {
  if (states.contains(MaterialState.hovered)) {
    return Colors.yellow;
  }
  return null;
}
