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

import '../rendering/mock_canvas.dart';
import '../widgets/semantics_tester.dart';

const CupertinoDynamicColor _kSystemFill = CupertinoDynamicColor(
  color: Color.fromARGB(51, 120, 120, 128),
  darkColor: Color.fromARGB(91, 120, 120, 128),
  highContrastColor: Color.fromARGB(71, 120, 120, 128),
  darkHighContrastColor: Color.fromARGB(112, 120, 120, 128),
  elevatedColor: Color.fromARGB(51, 120, 120, 128),
  darkElevatedColor: Color.fromARGB(91, 120, 120, 128),
  highContrastElevatedColor: Color.fromARGB(71, 120, 120, 128),
  darkHighContrastElevatedColor: Color.fromARGB(112, 120, 120, 128),
);

void main() {

  Future<void> _dragSlider(WidgetTester tester, Key sliderKey) {
    final Offset topLeft = tester.getTopLeft(find.byKey(sliderKey));
    const double unit = CupertinoThumbPainter.radius;
    const double delta = 3.0 * unit;
    return tester.dragFrom(topLeft + const Offset(unit, unit), const Offset(delta, 0.0));
  }

  testWidgets('Slider does not move when tapped (LTR)', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;

    await tester.pumpWidget(
      CupertinoApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: CupertinoSlider(
                    key: sliderKey,
                    value: value,
                    onChanged: (double newValue) {
                      setState(() { value = newValue; });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(value, equals(0.0));
    await tester.tap(find.byKey(sliderKey), warnIfMissed: false);
    expect(value, equals(0.0));
    await tester.pump(); // No animation should start.
    // Check the transientCallbackCount before tearing down the widget to ensure
    // that no animation is running.
    expect(SchedulerBinding.instance!.transientCallbackCount, equals(0));
  });

  testWidgets('Slider does not move when tapped (RTL)', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;

    await tester.pumpWidget(
      CupertinoApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: CupertinoSlider(
                    key: sliderKey,
                    value: value,
                    onChanged: (double newValue) {
                      setState(() { value = newValue; });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(value, equals(0.0));
    await tester.tap(find.byKey(sliderKey), warnIfMissed: false);
    expect(value, equals(0.0));
    await tester.pump(); // No animation should start.
    // Check the transientCallbackCount before tearing down the widget to ensure
    // that no animation is running.
    expect(SchedulerBinding.instance!.transientCallbackCount, equals(0));
  });

  testWidgets('Slider calls onChangeStart once when interaction begins', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;
    int numberOfTimesOnChangeStartIsCalled = 0;

    await tester.pumpWidget(
      CupertinoApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: CupertinoSlider(
                    key: sliderKey,
                    value: value,
                    onChanged: (double newValue) {
                      setState(() { value = newValue; });
                    },
                    onChangeStart: (double value) {
                      numberOfTimesOnChangeStartIsCalled++;
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    await _dragSlider(tester, sliderKey);

    expect(numberOfTimesOnChangeStartIsCalled, equals(1));

    await tester.pump(); // No animation should start.
    // Check the transientCallbackCount before tearing down the widget to ensure
    // that no animation is running.
    expect(SchedulerBinding.instance!.transientCallbackCount, equals(0));
  });

  testWidgets('Slider calls onChangeEnd once after interaction has ended', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;
    int numberOfTimesOnChangeEndIsCalled = 0;

    await tester.pumpWidget(
      CupertinoApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: CupertinoSlider(
                    key: sliderKey,
                    value: value,
                    onChanged: (double newValue) {
                      setState(() { value = newValue; });
                    },
                    onChangeEnd: (double value) {
                      numberOfTimesOnChangeEndIsCalled++;
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    await _dragSlider(tester, sliderKey);

    expect(numberOfTimesOnChangeEndIsCalled, equals(1));

    await tester.pump(); // No animation should start.
    // Check the transientCallbackCount before tearing down the widget to ensure
    // that no animation is running.
    expect(SchedulerBinding.instance!.transientCallbackCount, equals(0));
  });

  testWidgets('Slider moves when dragged (LTR)', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;
    late double startValue;
    late double endValue;

    await tester.pumpWidget(
      CupertinoApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: CupertinoSlider(
                    key: sliderKey,
                    value: value,
                    onChanged: (double newValue) {
                      setState(() { value = newValue; });
                    },
                    onChangeStart: (double value) {
                      startValue = value;
                    },
                    onChangeEnd: (double value) {
                      endValue = value;
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(value, equals(0.0));

    final Offset topLeft = tester.getTopLeft(find.byKey(sliderKey));
    const double unit = CupertinoThumbPainter.radius;
    const double delta = 3.0 * unit;
    await tester.dragFrom(topLeft + const Offset(unit, unit), const Offset(delta, 0.0));

    final Size size = tester.getSize(find.byKey(sliderKey));
    final double finalValue = delta / (size.width - 2.0 * (8.0 + CupertinoThumbPainter.radius));
    expect(startValue, equals(0.0));
    expect(value, equals(finalValue));
    expect(endValue, equals(finalValue));

    await tester.pump(); // No animation should start.
    // Check the transientCallbackCount before tearing down the widget to ensure
    // that no animation is running.
    expect(SchedulerBinding.instance!.transientCallbackCount, equals(0));
  });

  testWidgets('Slider moves when dragged (RTL)', (WidgetTester tester) async {
    final Key sliderKey = UniqueKey();
    double value = 0.0;
    late double startValue;
    late double endValue;

    await tester.pumpWidget(
      CupertinoApp(
        home: Directionality(
          textDirection: TextDirection.rtl,
          child: StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Material(
                child: Center(
                  child: CupertinoSlider(
                    key: sliderKey,
                    value: value,
                    onChanged: (double newValue) {
                      setState(() { value = newValue; });
                    },
                    onChangeStart: (double value) {
                      setState(() { startValue = value; });
                    },
                    onChangeEnd: (double value) {
                      setState(() { endValue = value; });
                    },
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(value, equals(0.0));

    final Offset bottomRight = tester.getBottomRight(find.byKey(sliderKey));
    const double unit = CupertinoThumbPainter.radius;
    const double delta = 3.0 * unit;
    await tester.dragFrom(bottomRight - const Offset(unit, unit), const Offset(-delta, 0.0));

    final Size size = tester.getSize(find.byKey(sliderKey));
    final double finalValue = delta / (size.width - 2.0 * (8.0 + CupertinoThumbPainter.radius));
    expect(startValue, equals(0.0));
    expect(value, equals(finalValue));
    expect(endValue, equals(finalValue));

    await tester.pump(); // No animation should start.
    // Check the transientCallbackCount before tearing down the widget to ensure
    // that no animation is running.
    expect(SchedulerBinding.instance!.transientCallbackCount, equals(0));
  });

  testWidgets('Slider Semantics', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);

    await tester.pumpWidget(
      MediaQuery(
        data: const MediaQueryData(),
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: CupertinoSlider(
            value: 0.5,
            onChanged: (double v) { },
          ),
        ),
      ),
    );

    expect(semantics, hasSemantics(
      TestSemantics.root(
        children: <TestSemantics>[
          TestSemantics.rootChild(
            id: 1,
            value: '50%',
            increasedValue: '60%',
            decreasedValue: '40%',
            textDirection: TextDirection.ltr,
            flags: <SemanticsFlag>[SemanticsFlag.isSlider],
            actions: SemanticsAction.decrease.index | SemanticsAction.increase.index,
          ),
        ],
      ),
      ignoreRect: true,
      ignoreTransform: true,
    ));

    // Disable slider
    await tester.pumpWidget(
      const MediaQuery(
        data: MediaQueryData(),
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: CupertinoSlider(
            value: 0.5,
            onChanged: null,
          ),
        ),
      ),
    );

    expect(semantics, hasSemantics(
      TestSemantics.root(
        children: <TestSemantics>[
          TestSemantics(
            id: 1,
            flags: <SemanticsFlag>[SemanticsFlag.isSlider],
          ),
        ],
      ),
      ignoreRect: true,
      ignoreTransform: true,
    ));

    semantics.dispose();
  });

  testWidgets('Slider Semantics can be updated', (WidgetTester tester) async {
    final SemanticsHandle handle = tester.ensureSemantics();
    double value = 0.5;
    await tester.pumpWidget(
      CupertinoApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: CupertinoSlider(
            value: value,
            onChanged: (double v) { },
          ),
        ),
      ),
    );

    expect(tester.getSemantics(find.byType(CupertinoSlider)), matchesSemantics(
      isSlider: true,
      hasIncreaseAction: true,
      hasDecreaseAction: true,
      value: '50%',
      increasedValue: '60%',
      decreasedValue: '40%',
      textDirection: TextDirection.ltr,
    ));

    value = 0.6;
    await tester.pumpWidget(
      CupertinoApp(
        home: Directionality(
          textDirection: TextDirection.ltr,
          child: CupertinoSlider(
            value: value,
            onChanged: (double v) { },
          ),
        ),
      ),
    );

    expect(tester.getSemantics(find.byType(CupertinoSlider)), matchesSemantics(
      isSlider: true,
      hasIncreaseAction: true,
      hasDecreaseAction: true,
      value: '60%',
      increasedValue: '70%',
      decreasedValue: '50%',
      textDirection: TextDirection.ltr,
    ));

    handle.dispose();
  });

  testWidgets('Slider respects themes', (WidgetTester tester) async {
    await tester.pumpWidget(
      CupertinoApp(
        home: Center(
          child: CupertinoSlider(
            onChanged: (double value) { },
            value: 0.5,
          ),
        ),
      ),
    );
    expect(
      find.byType(CupertinoSlider),
      // First line it paints is blue.
      paints..rrect(color: CupertinoColors.systemBlue.color),
    );

    await tester.pumpWidget(
      CupertinoApp(
        theme: const CupertinoThemeData(brightness: Brightness.dark),
        home: Center(
          child: CupertinoSlider(
            onChanged: (double value) { },
            value: 0.5,
          ),
        ),
      ),
    );

    expect(
      find.byType(CupertinoSlider),
      paints..rrect(color: CupertinoColors.systemBlue.darkColor),
    );
  });

  testWidgets('Themes can be overridden', (WidgetTester tester) async {
    await tester.pumpWidget(
      CupertinoApp(
        theme: const CupertinoThemeData(brightness: Brightness.dark),
        home: Center(
          child: CupertinoSlider(
            activeColor: CupertinoColors.activeGreen,
            onChanged: (double value) { },
            value: 0.5,
          ),
        ),
      ),
    );
    expect(
      find.byType(CupertinoSlider),
      paints..rrect(color: CupertinoColors.systemGreen.darkColor),
    );
  });

  testWidgets('Themes can be overridden by dynamic colors', (WidgetTester tester) async {
    const CupertinoDynamicColor activeColor = CupertinoDynamicColor(
      color: Color(0x00000001),
      darkColor: Color(0x00000002),
      elevatedColor: Color(0x00000003),
      highContrastColor: Color(0x00000004),
      darkElevatedColor: Color(0x00000005),
      darkHighContrastColor: Color(0x00000006),
      highContrastElevatedColor: Color(0x00000007),
      darkHighContrastElevatedColor: Color(0x00000008),
    );

    Widget withTraits(Brightness brightness, CupertinoUserInterfaceLevelData level, bool highContrast) {
      return CupertinoTheme(
        data: CupertinoThemeData(brightness: brightness),
        child: CupertinoUserInterfaceLevel(
          data: level,
          child: MediaQuery(
            data: MediaQueryData(highContrast: highContrast),
            child: Center(
              child: CupertinoSlider(
                activeColor: activeColor,
                onChanged: (double value) { },
                value: 0.5,
              ),
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(CupertinoApp(home: withTraits(Brightness.light, CupertinoUserInterfaceLevelData.base, false)));
    expect(find.byType(CupertinoSlider), paints..rrect(color: activeColor.color));

    await tester.pumpWidget(CupertinoApp(home: withTraits(Brightness.dark, CupertinoUserInterfaceLevelData.base, false)));
    expect(find.byType(CupertinoSlider), paints..rrect(color: activeColor.darkColor));

    await tester.pumpWidget(CupertinoApp(home: withTraits(Brightness.dark, CupertinoUserInterfaceLevelData.elevated, false)));
    expect(find.byType(CupertinoSlider), paints..rrect(color: activeColor.darkElevatedColor));

    await tester.pumpWidget(CupertinoApp(home: withTraits(Brightness.dark, CupertinoUserInterfaceLevelData.base, true)));
    expect(find.byType(CupertinoSlider), paints..rrect(color: activeColor.darkHighContrastColor));

    await tester.pumpWidget(CupertinoApp(home: withTraits(Brightness.dark, CupertinoUserInterfaceLevelData.elevated, true)));
    expect(find.byType(CupertinoSlider), paints..rrect(color: activeColor.darkHighContrastElevatedColor));

    await tester.pumpWidget(CupertinoApp(home: withTraits(Brightness.light, CupertinoUserInterfaceLevelData.base, true)));
    expect(find.byType(CupertinoSlider), paints..rrect(color: activeColor.highContrastColor));

    await tester.pumpWidget(CupertinoApp(home: withTraits(Brightness.light, CupertinoUserInterfaceLevelData.elevated, false)));
    expect(find.byType(CupertinoSlider), paints..rrect(color: activeColor.elevatedColor));

    await tester.pumpWidget(CupertinoApp(home: withTraits(Brightness.light, CupertinoUserInterfaceLevelData.elevated, true)));
    expect(find.byType(CupertinoSlider), paints..rrect(color: activeColor.highContrastElevatedColor));
  });

  testWidgets('track color is dynamic', (WidgetTester tester) async {
    await tester.pumpWidget(
      CupertinoApp(
        theme: const CupertinoThemeData(brightness: Brightness.light),
        home: Center(
          child: CupertinoSlider(
            activeColor: CupertinoColors.activeGreen,
            onChanged: (double value) { },
            value: 0,
          ),
        ),
      ),
    );

    expect(
      find.byType(CupertinoSlider),
      paints..rrect(color: _kSystemFill.color),
    );

    expect(
      find.byType(CupertinoSlider),
      isNot(paints..rrect(color: _kSystemFill.darkColor)),
    );

    await tester.pumpWidget(
      CupertinoApp(
        theme: const CupertinoThemeData(brightness: Brightness.dark),
        home: Center(
          child: CupertinoSlider(
            activeColor: CupertinoColors.activeGreen,
            onChanged: (double value) { },
            value: 0,
          ),
        ),
      ),
    );

    expect(
      find.byType(CupertinoSlider),
      paints..rrect(color: _kSystemFill.darkColor),
    );

    expect(
      find.byType(CupertinoSlider),
      isNot(paints..rrect(color: _kSystemFill.color)),
    );
  });

  testWidgets('Thumb color can be overridden', (WidgetTester tester) async {
    await tester.pumpWidget(
      CupertinoApp(
        home: Center(
          child: CupertinoSlider(
            thumbColor: CupertinoColors.systemPurple,
            onChanged: (double value) { },
            value: 0,
          ),
        ),
      ),
    );

    expect(
      find.byType(CupertinoSlider),
      paints
      ..rrect()
      ..rrect()
      ..rrect()
      ..rrect()
      ..rrect()
      ..rrect(color: CupertinoColors.systemPurple.color),
    );

    await tester.pumpWidget(
      CupertinoApp(
        home: Center(
          child: CupertinoSlider(
            thumbColor: CupertinoColors.activeOrange,
            onChanged: (double value) { },
            value: 0,
          ),
        ),
      ),
    );

    expect(
        find.byType(CupertinoSlider),
        paints
          ..rrect()
          ..rrect()
          ..rrect()
          ..rrect()
          ..rrect()
          ..rrect(color: CupertinoColors.activeOrange.color),
    );
  });
}
