// 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';

void main() {
  test('ButtonThemeData defaults', () {
    const ButtonThemeData theme = ButtonThemeData();
    expect(theme.textTheme, ButtonTextTheme.normal);
    expect(theme.constraints, const BoxConstraints(minWidth: 88.0, minHeight: 36.0));
    expect(theme.padding, const EdgeInsets.symmetric(horizontal: 16.0));
    expect(theme.shape, const RoundedRectangleBorder(
      borderRadius: BorderRadius.all(Radius.circular(2.0)),
    ));
    expect(theme.alignedDropdown, false);
    expect(theme.layoutBehavior, ButtonBarLayoutBehavior.padded);
  });

  test('ButtonThemeData default overrides', () {
    const ButtonThemeData theme = ButtonThemeData(
      textTheme: ButtonTextTheme.primary,
      minWidth: 100.0,
      height: 200.0,
      padding: EdgeInsets.zero,
      shape: RoundedRectangleBorder(),
      alignedDropdown: true,
    );
    expect(theme.textTheme, ButtonTextTheme.primary);
    expect(theme.constraints, const BoxConstraints(minWidth: 100.0, minHeight: 200.0));
    expect(theme.padding, EdgeInsets.zero);
    expect(theme.shape, const RoundedRectangleBorder());
    expect(theme.alignedDropdown, true);
  });

  testWidgets('ButtonTheme defaults', (WidgetTester tester) async {
    late ButtonTextTheme textTheme;
    late ButtonBarLayoutBehavior layoutBehavior;
    late BoxConstraints constraints;
    late EdgeInsets padding;
    late ShapeBorder shape;
    late bool alignedDropdown;
    late ColorScheme colorScheme;

    await tester.pumpWidget(
      ButtonTheme(
        child: Builder(
          builder: (BuildContext context) {
            final ButtonThemeData theme = ButtonTheme.of(context);
            textTheme = theme.textTheme;
            constraints = theme.constraints;
            padding = theme.padding as EdgeInsets;
            shape = theme.shape;
            layoutBehavior = theme.layoutBehavior;
            colorScheme = theme.colorScheme!;
            alignedDropdown = theme.alignedDropdown;
            return Container(
              alignment: Alignment.topLeft,
              child: Directionality(
                textDirection: TextDirection.ltr,
                child: FlatButton(
                  onPressed: () { },
                  child: const Text('b'), // intrinsic width < minimum width
                ),
              ),
            );
          },
        ),
      ),
    );

    expect(textTheme, ButtonTextTheme.normal);
    expect(layoutBehavior, ButtonBarLayoutBehavior.padded);
    expect(constraints, const BoxConstraints(minWidth: 88.0, minHeight: 36.0));
    expect(padding, const EdgeInsets.symmetric(horizontal: 16.0));
    expect(shape, const RoundedRectangleBorder(
      borderRadius: BorderRadius.all(Radius.circular(2.0)),
    ));
    expect(alignedDropdown, false);
    expect(colorScheme, ThemeData.light().colorScheme);
    expect(tester.widget<Material>(find.byType(Material)).shape, shape);
    expect(tester.getSize(find.byType(Material)), const Size(88.0, 36.0));
  });

  test('ButtonThemeData.copyWith', () {
    ButtonThemeData theme = const ButtonThemeData().copyWith();
    expect(theme.textTheme, ButtonTextTheme.normal);
    expect(theme.layoutBehavior, ButtonBarLayoutBehavior.padded);
    expect(theme.constraints, const BoxConstraints(minWidth: 88.0, minHeight: 36.0));
    expect(theme.padding, const EdgeInsets.symmetric(horizontal: 16.0));
    expect(theme.shape, const RoundedRectangleBorder(
      borderRadius: BorderRadius.all(Radius.circular(2.0)),
    ));
    expect(theme.alignedDropdown, false);
    expect(theme.colorScheme, null);

    theme = const ButtonThemeData().copyWith(
      textTheme: ButtonTextTheme.primary,
      layoutBehavior: ButtonBarLayoutBehavior.constrained,
      minWidth: 100.0,
      height: 200.0,
      padding: EdgeInsets.zero,
      shape: const StadiumBorder(),
      alignedDropdown: true,
      colorScheme: const ColorScheme.dark(),
      materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
    );
    expect(theme.textTheme, ButtonTextTheme.primary);
    expect(theme.layoutBehavior, ButtonBarLayoutBehavior.constrained);
    expect(theme.constraints, const BoxConstraints(minWidth: 100.0, minHeight: 200.0));
    expect(theme.padding, EdgeInsets.zero);
    expect(theme.shape, const StadiumBorder());
    expect(theme.alignedDropdown, true);
    expect(theme.colorScheme, const ColorScheme.dark());
  });

  testWidgets('Theme buttonTheme defaults', (WidgetTester tester) async {
    final ThemeData lightTheme = ThemeData.light();
    late ButtonTextTheme textTheme;
    late BoxConstraints constraints;
    late EdgeInsets padding;
    late ShapeBorder shape;

    const Color disabledColor = Color(0xFF00FF00);
    await tester.pumpWidget(
      Theme(
        data: lightTheme.copyWith(
          disabledColor: disabledColor, // disabled RaisedButton fill color
          buttonTheme: const ButtonThemeData(disabledColor: disabledColor),
          textTheme: lightTheme.textTheme.copyWith(
            button: lightTheme.textTheme.button!.copyWith(
              // The button's height will match because there's no
              // vertical padding by default
              fontSize: 48.0,
            ),
          ),
        ),
        child: Builder(
          builder: (BuildContext context) {
            final ButtonThemeData theme = ButtonTheme.of(context);
            textTheme = theme.textTheme;
            constraints = theme.constraints;
            padding = theme.padding as EdgeInsets;
            shape = theme.shape;
            return Container(
              alignment: Alignment.topLeft,
              child: const Directionality(
                textDirection: TextDirection.ltr,
                child: RaisedButton(
                  onPressed: null,
                  child: Text('b'), // intrinsic width < minimum width
                ),
              ),
            );
          },
        ),
      ),
    );

    expect(textTheme, ButtonTextTheme.normal);
    expect(constraints, const BoxConstraints(minWidth: 88.0, minHeight: 36.0));
    expect(padding, const EdgeInsets.symmetric(horizontal: 16.0));
    expect(shape, const RoundedRectangleBorder(
      borderRadius: BorderRadius.all(Radius.circular(2.0)),
    ));

    expect(tester.widget<Material>(find.byType(Material)).shape, shape);
    expect(tester.widget<Material>(find.byType(Material)).color, disabledColor);
    expect(tester.getSize(find.byType(Material)), const Size(88.0, 48.0));
  });

  testWidgets('Theme buttonTheme ButtonTheme overrides', (WidgetTester tester) async {
    late ButtonTextTheme textTheme;
    late BoxConstraints constraints;
    late EdgeInsets padding;
    late ShapeBorder shape;

    await tester.pumpWidget(
      Theme(
        data: ThemeData.light().copyWith(
          buttonColor: const Color(0xFF00FF00), // enabled RaisedButton fill color
        ),
        child: ButtonTheme(
          textTheme: ButtonTextTheme.primary,
          minWidth: 100.0,
          height: 200.0,
          padding: EdgeInsets.zero,
          buttonColor: const Color(0xFF00FF00), // enabled RaisedButton fill color
          shape: const RoundedRectangleBorder(),
          child: Builder(
            builder: (BuildContext context) {
              final ButtonThemeData theme = ButtonTheme.of(context);
              textTheme = theme.textTheme;
              constraints = theme.constraints;
              padding = theme.padding as EdgeInsets;
              shape = theme.shape;
              return Container(
                alignment: Alignment.topLeft,
                child: Directionality(
                  textDirection: TextDirection.ltr,
                  child: RaisedButton(
                    onPressed: () { },
                    child: const Text('b'), // intrinsic width < minimum width
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );

    expect(textTheme, ButtonTextTheme.primary);
    expect(constraints, const BoxConstraints(minWidth: 100.0, minHeight: 200.0));
    expect(padding, EdgeInsets.zero);
    expect(shape, const RoundedRectangleBorder());

    expect(tester.widget<Material>(find.byType(Material)).shape, shape);
    expect(tester.widget<Material>(find.byType(Material)).color, const Color(0xFF00FF00));
    expect(tester.getSize(find.byType(Material)), const Size(100.0, 200.0));
  });

  testWidgets('ButtonTheme alignedDropdown', (WidgetTester tester) async {
    final Key dropdownKey = UniqueKey();

    Widget buildFrame({ required bool alignedDropdown, required TextDirection textDirection }) {
      return MaterialApp(
        builder: (BuildContext context, Widget? child) {
          return Directionality(
            textDirection: textDirection,
            child: child!,
          );
        },
        home: ButtonTheme(
          alignedDropdown: alignedDropdown,
          child: Material(
            child: Builder(
              builder: (BuildContext context) {
                return Container(
                  alignment: Alignment.center,
                  child: DropdownButtonHideUnderline(
                    child: Container(
                      width: 200.0,
                      child: DropdownButton<String>(
                        key: dropdownKey,
                        onChanged: (String? value) { },
                        value: 'foo',
                        items: const <DropdownMenuItem<String>>[
                          DropdownMenuItem<String>(
                            value: 'foo',
                            child: Text('foo'),
                          ),
                          DropdownMenuItem<String>(
                            value: 'bar',
                            child: Text('bar'),
                          ),
                        ],
                      ),
                    ),
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    final Finder button = find.byKey(dropdownKey);
    final Finder menu = find.byWidgetPredicate((Widget w) => '${w.runtimeType}' == '_DropdownMenu<String>');

    await tester.pumpWidget(
      buildFrame(
        alignedDropdown: false,
        textDirection: TextDirection.ltr,
      ),
    );
    await tester.tap(button);
    await tester.pumpAndSettle();

    // 240 = 200.0 (button width) + _kUnalignedMenuMargin (20.0 left and right)
    expect(tester.getSize(button).width, 200.0);
    expect(tester.getSize(menu).width, 240.0);

    // Dismiss the menu.
    await tester.tapAt(Offset.zero);
    await tester.pumpAndSettle();
    expect(menu, findsNothing);

    await tester.pumpWidget(
      buildFrame(
        alignedDropdown: true,
        textDirection: TextDirection.ltr,
      ),
    );
    await tester.tap(button);
    await tester.pumpAndSettle();

    // Aligneddropdown: true means the button and menu widths match
    expect(tester.getSize(button).width, 200.0);
    expect(tester.getSize(menu).width, 200.0);

    // There are two 'foo' widgets: the selected menu item's label and the drop
    // down button's label. The should both appear at the same location.
    final Finder fooText = find.text('foo');
    expect(fooText, findsNWidgets(2));
    expect(tester.getRect(fooText.at(0)), tester.getRect(fooText.at(1)));

    // Dismiss the menu.
    await tester.tapAt(Offset.zero);
    await tester.pumpAndSettle();
    expect(menu, findsNothing);

    // Same test as above except RTL
    await tester.pumpWidget(
      buildFrame(
        alignedDropdown: true,
        textDirection: TextDirection.rtl,
      ),
    );
    await tester.tap(button);
    await tester.pumpAndSettle();

    expect(fooText, findsNWidgets(2));
    expect(tester.getRect(fooText.at(0)), tester.getRect(fooText.at(1)));
  });

  testWidgets('button theme with stateful color changes color in states', (WidgetTester tester) async {
    final FocusNode focusNode = FocusNode();

    const Color pressedColor = Color(0x00000001);
    const Color hoverColor = Color(0x00000002);
    const Color focusedColor = Color(0x00000003);
    const Color defaultColor = Color(0x00000004);

    Color getTextColor(Set<MaterialState> states) {
      if (states.contains(MaterialState.pressed)) {
        return pressedColor;
      }
      if (states.contains(MaterialState.hovered)) {
        return hoverColor;
      }
      if (states.contains(MaterialState.focused)) {
        return focusedColor;
      }
      return defaultColor;
    }

    const ColorScheme colorScheme = ColorScheme.light();

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: Center(
            child: ButtonTheme(
              colorScheme: colorScheme.copyWith(
                primary: MaterialStateColor.resolveWith(getTextColor),
              ),
              textTheme: ButtonTextTheme.primary,
              child: FlatButton(
                child: const Text('FlatButton'),
                onPressed: () {},
                focusNode: focusNode,
              ),
            ),
          ),
        ),
      ),
    );

    Color textColor() {
      return tester.renderObject<RenderParagraph>(find.text('FlatButton')).text.style!.color!;
    }

    // Default, not disabled.
    expect(textColor(), equals(defaultColor));

    // Focused.
    focusNode.requestFocus();
    await tester.pumpAndSettle();
    expect(textColor(), focusedColor);

    // Hovered.
    final Offset center = tester.getCenter(find.byType(FlatButton));
    final TestGesture gesture = await tester.createGesture(
      kind: PointerDeviceKind.mouse,
    );
    await gesture.addPointer(location: Offset.zero);
    addTearDown(gesture.removePointer);
    await gesture.moveTo(center);
    await tester.pumpAndSettle();
    expect(textColor(), hoverColor);

    // Highlighted (pressed).
    await gesture.down(center);
    await tester.pump(); // Start the splash and highlight animations.
    await tester.pump(const Duration(milliseconds: 800)); // Wait for splash and highlight to be well under way.
    expect(textColor(), pressedColor);
  },
    semanticsEnabled: true,
  );
}
