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

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

Widget boilerplate({required Widget child}) {
  return Directionality(
    textDirection: TextDirection.ltr,
    child: Center(child: child),
  );
}

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

  test('ToggleButtonsThemeData defaults', () {
    const ToggleButtonsThemeData themeData = ToggleButtonsThemeData();
    expect(themeData.textStyle, null);
    expect(themeData.constraints, null);
    expect(themeData.color, null);
    expect(themeData.selectedColor, null);
    expect(themeData.disabledColor, null);
    expect(themeData.fillColor, null);
    expect(themeData.focusColor, null);
    expect(themeData.highlightColor, null);
    expect(themeData.hoverColor, null);
    expect(themeData.splashColor, null);
    expect(themeData.borderColor, null);
    expect(themeData.selectedBorderColor, null);
    expect(themeData.disabledBorderColor, null);
    expect(themeData.borderRadius, null);
    expect(themeData.borderWidth, null);

    const ToggleButtonsTheme theme = ToggleButtonsTheme(data: ToggleButtonsThemeData(), child: SizedBox());
    expect(theme.data.textStyle, null);
    expect(theme.data.constraints, null);
    expect(theme.data.color, null);
    expect(theme.data.selectedColor, null);
    expect(theme.data.disabledColor, null);
    expect(theme.data.fillColor, null);
    expect(theme.data.focusColor, null);
    expect(theme.data.highlightColor, null);
    expect(theme.data.hoverColor, null);
    expect(theme.data.splashColor, null);
    expect(theme.data.borderColor, null);
    expect(theme.data.selectedBorderColor, null);
    expect(theme.data.disabledBorderColor, null);
    expect(theme.data.borderRadius, null);
    expect(theme.data.borderWidth, null);
  });

  testWidgets('Default ToggleButtonsThemeData debugFillProperties', (WidgetTester tester) async {
    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
    const ToggleButtonsThemeData().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('ToggleButtonsThemeData implements debugFillProperties', (WidgetTester tester) async {
    final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
    const ToggleButtonsThemeData(
      textStyle: TextStyle(fontSize: 10),
      constraints: BoxConstraints(minHeight: 10.0, maxHeight: 20.0),
      color: Color(0xfffffff0),
      selectedColor: Color(0xfffffff1),
      disabledColor: Color(0xfffffff2),
      fillColor: Color(0xfffffff3),
      focusColor: Color(0xfffffff4),
      highlightColor: Color(0xfffffff5),
      hoverColor: Color(0xfffffff6),
      splashColor: Color(0xfffffff7),
      borderColor: Color(0xfffffff8),
      selectedBorderColor: Color(0xfffffff9),
      disabledBorderColor: Color(0xfffffffa),
      borderRadius: BorderRadius.all(Radius.circular(4.0)),
      borderWidth: 2.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>[
      'textStyle.inherit: true',
      'textStyle.size: 10.0',
      'constraints: BoxConstraints(0.0<=w<=Infinity, 10.0<=h<=20.0)',
      'color: Color(0xfffffff0)',
      'selectedColor: Color(0xfffffff1)',
      'disabledColor: Color(0xfffffff2)',
      'fillColor: Color(0xfffffff3)',
      'focusColor: Color(0xfffffff4)',
      'highlightColor: Color(0xfffffff5)',
      'hoverColor: Color(0xfffffff6)',
      'splashColor: Color(0xfffffff7)',
      'borderColor: Color(0xfffffff8)',
      'selectedBorderColor: Color(0xfffffff9)',
      'disabledBorderColor: Color(0xfffffffa)',
      'borderRadius: BorderRadius.circular(4.0)',
      'borderWidth: 2.0',
    ]);
  });

  testWidgets('Theme text style, except color, is applied', (WidgetTester tester) async {
    await tester.pumpWidget(
      Material(
        child: boilerplate(
          child: ToggleButtonsTheme(
            data: const ToggleButtonsThemeData(
              textStyle: TextStyle(
                color: Colors.orange,
                textBaseline: TextBaseline.ideographic,
                fontSize: 20.0,
              ),
            ),
            child: ToggleButtons(
              isSelected: const <bool>[false, true],
              onPressed: (int index) {},
              children: const <Widget>[
                Text('First child'),
                Text('Second child'),
              ],
            ),
          ),
        ),
      ),
    );

    TextStyle textStyle;
    textStyle = tester.widget<DefaultTextStyle>(find.descendant(
      of: find.widgetWithText(TextButton, 'First child'),
      matching: find.byType(DefaultTextStyle),
    )).style;
    expect(textStyle.textBaseline, TextBaseline.ideographic);
    expect(textStyle.fontSize, 20.0);
    expect(textStyle.color, isNot(Colors.orange));

    textStyle = tester.widget<DefaultTextStyle>(find.descendant(
        of: find.widgetWithText(TextButton, 'Second child'),
        matching: find.byType(DefaultTextStyle),
    )).style;
    expect(textStyle.textBaseline, TextBaseline.ideographic);
    expect(textStyle.fontSize, 20.0);
    expect(textStyle.color, isNot(Colors.orange));
  });

  testWidgets('Custom BoxConstraints', (WidgetTester tester) async {
    // Test for minimum constraints
    await tester.pumpWidget(
      Material(
        child: boilerplate(
          child: ToggleButtonsTheme(
            data: const ToggleButtonsThemeData(
              constraints: BoxConstraints(
                minWidth: 50.0,
                minHeight: 60.0,
              ),
            ),
            child: ToggleButtons(
              tapTargetSize: MaterialTapTargetSize.shrinkWrap,
              isSelected: const <bool>[false, false, false],
              onPressed: (int index) {},
              children: const <Widget>[
                Icon(Icons.check),
                Icon(Icons.access_alarm),
                Icon(Icons.cake),
              ],
            ),
          ),
        ),
      ),
    );

    Rect firstRect = tester.getRect(find.byType(TextButton).at(0));
    expect(firstRect.width, 50.0);
    expect(firstRect.height, 60.0);
    Rect secondRect = tester.getRect(find.byType(TextButton).at(1));
    expect(secondRect.width, 50.0);
    expect(secondRect.height, 60.0);
    Rect thirdRect = tester.getRect(find.byType(TextButton).at(2));
    expect(thirdRect.width, 50.0);
    expect(thirdRect.height, 60.0);

    // Test for maximum constraints
    await tester.pumpWidget(
      Material(
        child: boilerplate(
          child: ToggleButtonsTheme(
            data: const ToggleButtonsThemeData(
              constraints: BoxConstraints(
                maxWidth: 20.0,
                maxHeight: 10.0,
              ),
            ),
            child: ToggleButtons(
              tapTargetSize: MaterialTapTargetSize.shrinkWrap,
              isSelected: const <bool>[false, false, false],
              onPressed: (int index) {},
              children: const <Widget>[
                Icon(Icons.check),
                Icon(Icons.access_alarm),
                Icon(Icons.cake),
              ],
            ),
          ),
        ),
      ),
    );

    firstRect = tester.getRect(find.byType(TextButton).at(0));
    expect(firstRect.width, 20.0);
    expect(firstRect.height, 10.0);
    secondRect = tester.getRect(find.byType(TextButton).at(1));
    expect(secondRect.width, 20.0);
    expect(secondRect.height, 10.0);
    thirdRect = tester.getRect(find.byType(TextButton).at(2));
    expect(thirdRect.width, 20.0);
    expect(thirdRect.height, 10.0);
  });

  testWidgets(
    'Theme text/icon colors for enabled, selected and disabled states',
    (WidgetTester tester) async {
      TextStyle buttonTextStyle(String text) {
        return tester.widget<DefaultTextStyle>(find.descendant(
          of: find.widgetWithText(TextButton, text),
          matching: find.byType(DefaultTextStyle),
        )).style;
      }
      IconTheme iconTheme(IconData icon) {
        return tester.widget(find.descendant(
          of: find.widgetWithIcon(TextButton, icon),
          matching: find.byType(IconTheme),
        ));
      }
      final ThemeData theme = ThemeData();
      const Color enabledColor = Colors.lime;
      const Color selectedColor = Colors.green;
      const Color disabledColor = Colors.yellow;

      await tester.pumpWidget(
        Material(
          child: boilerplate(
            child: ToggleButtonsTheme(
              data: const ToggleButtonsThemeData(),
              child: ToggleButtons(
                color: enabledColor,
                isSelected: const <bool>[false],
                onPressed: (int index) {},
                children: <Widget>[
                  // This Row is used like this to test for both TextStyle
                  // and IconTheme for Text and Icon widgets respectively.
                  Row(children: const <Widget>[
                    Text('First child'),
                    Icon(Icons.check),
                  ]),
                ],
              ),
            ),
          ),
        ),
      );
      // Custom theme enabled color
      expect(theme.colorScheme.onSurface, isNot(enabledColor));
      expect(buttonTextStyle('First child').color, enabledColor);
      expect(iconTheme(Icons.check).data.color, enabledColor);

      await tester.pumpWidget(
        Material(
          child: boilerplate(
            child: ToggleButtonsTheme(
              data: const ToggleButtonsThemeData(
                selectedColor: selectedColor,
              ),
              child: ToggleButtons(
                color: enabledColor,
                isSelected: const <bool>[true],
                onPressed: (int index) {},
                children: <Widget>[
                  Row(children: const <Widget>[
                    Text('First child'),
                    Icon(Icons.check),
                  ]),
                ],
              ),
            ),
          ),
        ),
      );
      await tester.pumpAndSettle();
      // Custom theme selected color
      expect(theme.colorScheme.primary, isNot(selectedColor));
      expect(buttonTextStyle('First child').color, selectedColor);
      expect(iconTheme(Icons.check).data.color, selectedColor);

      await tester.pumpWidget(
        Material(
          child: boilerplate(
            child: ToggleButtonsTheme(
              data: const ToggleButtonsThemeData(
                disabledColor: disabledColor,
              ),
              child: ToggleButtons(
                color: enabledColor,
                isSelected: const <bool>[false],
                children: <Widget>[
                  Row(children: const <Widget>[
                    Text('First child'),
                    Icon(Icons.check),
                  ]),
                ],
              ),
            ),
          ),
        ),
      );
      await tester.pumpAndSettle();
      // Custom theme disabled color
      expect(theme.disabledColor, isNot(disabledColor));
      expect(buttonTextStyle('First child').color, disabledColor);
      expect(iconTheme(Icons.check).data.color, disabledColor);
    },
  );

  testWidgets('Theme button fillColor', (WidgetTester tester) async {
    const Color customFillColor = Colors.green;
    await tester.pumpWidget(
      Material(
        child: boilerplate(
          child: ToggleButtonsTheme(
            data: const ToggleButtonsThemeData(fillColor: customFillColor),
            child: ToggleButtons(
              isSelected: const <bool>[true],
              onPressed: (int index) {},
              children: <Widget>[
                Row(children: const <Widget>[
                  Text('First child'),
                ]),
              ],
            ),
          ),
        ),
      ),
    );

    final Material material = tester.widget<Material>(find.descendant(
      of: find.byType(TextButton),
      matching: find.byType(Material),
    ));
    expect(material.color, customFillColor);
    expect(material.type, MaterialType.button);
  });

  testWidgets('Custom Theme button fillColor in different states', (WidgetTester tester) async {
    Material buttonColor(String text) {
      return tester.widget<Material>(
        find.descendant(
          of: find.byType(TextButton),
          matching: find.widgetWithText(Material, text),
        ),
      );
    }

    const Color enabledFillColor = Colors.green;
    const Color selectedFillColor = Colors.blue;
    const Color disabledFillColor = Colors.yellow;

    Color getColor(Set<MaterialState> states) {
      if (states.contains(MaterialState.selected)) {
        return selectedFillColor;
      } else if (states.contains(MaterialState.disabled)) {
        return disabledFillColor;
      }
      return enabledFillColor;
    }

    await tester.pumpWidget(
      Material(
        child: boilerplate(
          child: ToggleButtonsTheme(
            data: ToggleButtonsThemeData(fillColor: MaterialStateColor.resolveWith(getColor)),
            child: ToggleButtons(
              isSelected: const <bool>[true, false],
              onPressed: (int index) {},
              children: const <Widget> [
                Text('First child'),
                Text('Second child'),
              ],
            ),
          ),
        ),
      ),
    );

    await tester.pumpAndSettle();

    expect(buttonColor('First child').color, selectedFillColor);
    expect(buttonColor('Second child').color, enabledFillColor);

    await tester.pumpWidget(
      Material(
        child: boilerplate(
          child: ToggleButtonsTheme(
            data: ToggleButtonsThemeData(fillColor: MaterialStateColor.resolveWith(getColor)),
            child: ToggleButtons(
              isSelected: const <bool>[true, false],
              children: const <Widget>[
                Text('First child'),
                Text('Second child'),
              ],
            ),
          ),
        ),
      ),
    );

    expect(buttonColor('First child').color, disabledFillColor);
    expect(buttonColor('Second child').color, disabledFillColor);
  });

  testWidgets('Theme InkWell colors', (WidgetTester tester) async {
    const Color splashColor = Color(0xff4caf50);
    const Color highlightColor = Color(0xffcddc39);
    const Color hoverColor = Color(0xffffeb3b);
    const Color focusColor = Color(0xffffff00);
    final FocusNode focusNode = FocusNode();

    await tester.pumpWidget(
      Material(
        child: boilerplate(
          child: ToggleButtonsTheme(
            data: const ToggleButtonsThemeData(
              splashColor: splashColor,
              highlightColor: highlightColor,
              hoverColor: hoverColor,
              focusColor: focusColor,
            ),
            child: ToggleButtons(
              isSelected: const <bool>[true],
              onPressed: (int index) {},
              focusNodes: <FocusNode>[focusNode],
              children: const <Widget>[
                Text('First child'),
              ],
            ),
          ),
        ),
      ),
    );

    final Offset center = tester.getCenter(find.text('First child'));

    // splashColor
    // highlightColor
    final TestGesture touchGesture = await tester.createGesture();
    await touchGesture.down(center);
    await tester.pumpAndSettle();

    RenderObject inkFeatures;
    inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) {
      return object.runtimeType.toString() == '_RenderInkFeatures';
    });
    expect(
      inkFeatures,
      paints
        ..circle(color: splashColor)
    );

    await touchGesture.up();
    await tester.pumpAndSettle();

    // hoverColor
    final TestGesture hoverGesture = await tester.createGesture(
      kind: PointerDeviceKind.mouse,
    );
    await hoverGesture.addPointer();
    await hoverGesture.moveTo(center);
    await tester.pumpAndSettle();

    inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) {
      return object.runtimeType.toString() == '_RenderInkFeatures';
    });
    expect(inkFeatures, paints..rect(color: hoverColor));
    await hoverGesture.moveTo(Offset.zero);

    // focusColor
    focusNode.requestFocus();
    await tester.pumpAndSettle();
    inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) {
      return object.runtimeType.toString() == '_RenderInkFeatures';
    });
    expect(inkFeatures, paints..rect(color: focusColor));

    await hoverGesture.removePointer();
  });

  testWidgets(
    'Theme border width and border colors for enabled, selected and disabled states',
    (WidgetTester tester) async {
      const Color borderColor = Color(0xff4caf50);
      const Color selectedBorderColor = Color(0xffcddc39);
      const Color disabledBorderColor = Color(0xffffeb3b);
      const double customWidth = 2.0;

      await tester.pumpWidget(
        Material(
          child: boilerplate(
            child: ToggleButtonsTheme(
              data: const ToggleButtonsThemeData(
                borderColor: borderColor,
                borderWidth: customWidth,
              ),
              child: ToggleButtons(
                isSelected: const <bool>[false],
                onPressed: (int index) {},
                children: const <Widget>[
                  Text('First child'),
                ],
              ),
            ),
          ),
        ),
      );

      RenderObject toggleButtonRenderObject;
      toggleButtonRenderObject = tester.allRenderObjects.firstWhere((RenderObject object) {
        return object.runtimeType.toString() == '_SelectToggleButtonRenderObject';
      });
      expect(
        toggleButtonRenderObject,
        paints
          // physical model layer paint
          ..path()
          ..path(
            style: PaintingStyle.stroke,
            color: borderColor,
            strokeWidth: customWidth,
          ),
      );

      await tester.pumpWidget(
        Material(
          child: boilerplate(
            child: ToggleButtonsTheme(
              data: const ToggleButtonsThemeData(
                selectedBorderColor: selectedBorderColor,
                borderWidth: customWidth,
              ),
              child: ToggleButtons(
                isSelected: const <bool>[true],
                onPressed: (int index) {},
                children: const <Widget>[
                  Text('First child'),
                ],
              ),
            ),
          ),
        ),
      );

      toggleButtonRenderObject = tester.allRenderObjects.firstWhere((RenderObject object) {
        return object.runtimeType.toString() == '_SelectToggleButtonRenderObject';
      });
      expect(
        toggleButtonRenderObject,
        paints
          // physical model layer paint
          ..path()
          ..path(
            style: PaintingStyle.stroke,
            color: selectedBorderColor,
            strokeWidth: customWidth,
          ),
      );

      await tester.pumpWidget(
        Material(
          child: boilerplate(
            child: ToggleButtonsTheme(
              data: const ToggleButtonsThemeData(
                disabledBorderColor: disabledBorderColor,
                borderWidth: customWidth,
              ),
              child: ToggleButtons(
                isSelected: const <bool>[false],
                children: const <Widget>[
                  Text('First child'),
                ],
              ),
            ),
          ),
        ),
      );

      toggleButtonRenderObject = tester.allRenderObjects.firstWhere((RenderObject object) {
        return object.runtimeType.toString() == '_SelectToggleButtonRenderObject';
      });
      expect(
        toggleButtonRenderObject,
        paints
          // physical model layer paint
          ..path()
          ..path(
            style: PaintingStyle.stroke,
            color: disabledBorderColor,
            strokeWidth: customWidth,
          ),
      );
    },
  );
}
