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

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

void main() {
  testWidgets('Theme.wrap()', (WidgetTester tester) async {
    const Color primaryColor = Color(0xFF00FF00);
    final Key primaryContainerKey = UniqueKey();

    // Effectively the same as a StatelessWidget subclass.
    final Widget primaryBox = Builder(
      builder: (BuildContext context) {
        return Container(
          key: primaryContainerKey,
          color: Theme.of(context)!.primaryColor,
        );
      },
    );

    late BuildContext navigatorContext;

    Widget buildFrame() {
      return MaterialApp(
        home: Scaffold(
          body: Builder( // Introduce a context so the app's Theme is visible.
            builder: (BuildContext context) {
              navigatorContext = context;
              return Theme(
                data: Theme.of(context)!.copyWith(primaryColor: primaryColor),
                child: Builder( // Introduce a context so the shadow Theme is visible to captureAll().
                  builder: (BuildContext context) {
                    return Center(
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          ElevatedButton(
                            child: const Text('push unwrapped'),
                            onPressed: () {
                              Navigator.of(context)!.push<void>(
                                MaterialPageRoute<void>(
                                  // The primaryBox will see the default Theme when built.
                                  builder: (BuildContext _) => primaryBox,
                                ),
                              );
                            },
                          ),
                          ElevatedButton(
                            child: const Text('push wrapped'),
                            onPressed: () {
                              Navigator.of(context)!.push<void>(
                                MaterialPageRoute<void>(
                                  // Capture the shadow Theme.
                                  builder: (BuildContext _) => InheritedTheme.captureAll(context, primaryBox),
                                ),
                              );
                            },
                          ),
                        ],
                      ),
                    );
                  },
                ),
              );
            },
          ),
        ),
      );
    }

    Color containerColor() {
      return tester.widget<Container>(find.byKey(primaryContainerKey)).color!;
    }

    await tester.pumpWidget(buildFrame());

    // Show the route which contains primaryBox which was wrapped with
    // InheritedTheme.captureAll().
    await tester.tap(find.text('push wrapped'));
    await tester.pumpAndSettle(); // route animation
    expect(containerColor(), primaryColor);

    Navigator.of(navigatorContext)!.pop();
    await tester.pumpAndSettle(); // route animation

    // Show the route which contains primaryBox
    await tester.tap(find.text('push unwrapped'));
    await tester.pumpAndSettle(); // route animation
    expect(containerColor(), isNot(primaryColor));
  });

  testWidgets('PopupMenuTheme.wrap()', (WidgetTester tester) async {
    const double menuFontSize = 24;
    const Color menuTextColor = Color(0xFF0000FF);
    bool captureInheritedThemes = true;

    Widget buildFrame() {
      return MaterialApp(
        home: Scaffold(
          body: PopupMenuTheme(
            data: const PopupMenuThemeData(
              // The menu route's elevation, shape, and color are defined by the
              // current context, so they're not affected by ThemeData.captureAll().
              textStyle: TextStyle(fontSize: menuFontSize, color: menuTextColor),
            ),
            child: Center(
              child: PopupMenuButton<int>(
                // The appearance of the menu items' text is defined by the
                // PopupMenuTheme defined above. Popup menus use
                // InheritedTheme.captureAll() by default.
                captureInheritedThemes: captureInheritedThemes,
                child: const Text('show popupmenu'),
                onSelected: (int result) { },
                itemBuilder: (BuildContext context) {
                  return const <PopupMenuEntry<int>>[
                    PopupMenuItem<int>(value: 1, child: Text('One')),
                    PopupMenuItem<int>(value: 2, child: Text('Two')),
                  ];
                },
              ),
            ),
          ),
        ),
      );
    }

    TextStyle itemTextStyle(String text) {
      return tester.widget<RichText>(
        find.descendant(of: find.text(text), matching: find.byType(RichText)),
      ).text.style!;
    }

    await tester.pumpWidget(buildFrame());

    await tester.tap(find.text('show popupmenu'));
    await tester.pumpAndSettle(); // menu route animation
    expect(itemTextStyle('One').fontSize, menuFontSize);
    expect(itemTextStyle('One').color, menuTextColor);
    expect(itemTextStyle('Two').fontSize, menuFontSize);
    expect(itemTextStyle('Two').color, menuTextColor);

    // Dismiss the menu
    await tester.tap(find.text('One'));
    await tester.pumpAndSettle(); // menu route animation

    // Defeat the default support for capturing the PopupMenuTheme.
    captureInheritedThemes = false;
    await tester.pumpWidget(buildFrame());

    await tester.tap(find.text('show popupmenu'));
    await tester.pumpAndSettle(); // menu route animation
    expect(itemTextStyle('One').fontSize, isNot(menuFontSize));
    expect(itemTextStyle('One').color,  isNot(menuTextColor));
    expect(itemTextStyle('Two').fontSize, isNot(menuFontSize));
    expect(itemTextStyle('Two').color,  isNot(menuTextColor));
  });

  testWidgets('BannerTheme.wrap()', (WidgetTester tester) async {
    const Color bannerBackgroundColor = Color(0xFF0000FF);
    const double bannerFontSize = 48;
    const Color bannerTextColor = Color(0xFF00FF00);

    final Widget banner = MaterialBanner(
      content: const Text('hello'),
      actions: <Widget>[
        TextButton(
          child: const Text('action'),
          onPressed: () { },
        ),
      ],
    );

    late BuildContext navigatorContext;

    Widget buildFrame() {
      return MaterialApp(
        home: Scaffold(
          body: MaterialBannerTheme(
            data: const MaterialBannerThemeData(
              backgroundColor: bannerBackgroundColor,
              contentTextStyle: TextStyle(fontSize: bannerFontSize, color: bannerTextColor),
            ),
            child: Builder( // Introduce a context so the shadow BannerTheme is visible to captureAll().
              builder: (BuildContext context) {
                navigatorContext = context;
                return Center(
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      ElevatedButton(
                        child: const Text('push unwrapped'),
                        onPressed: () {
                          Navigator.of(context)!.push<void>(
                            MaterialPageRoute<void>(
                              // The Banner will see the default BannerTheme when built.
                              builder: (BuildContext _) => banner,
                            ),
                          );
                        },
                      ),
                      ElevatedButton(
                        child: const Text('push wrapped'),
                        onPressed: () {
                          Navigator.of(context)!.push<void>(
                            MaterialPageRoute<void>(
                              // Capture the shadow BannerTheme.
                              builder: (BuildContext _) => InheritedTheme.captureAll(context, banner),
                            ),
                          );
                        },
                      ),
                    ],
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    Color bannerColor() {
      return tester.widget<Container>(
        find.descendant(of: find.byType(MaterialBanner), matching: find.byType(Container)).first,
      ).color!;
    }

    TextStyle getTextStyle(String text) {
      return tester.widget<RichText>(
        find.descendant(
          of: find.text(text),
          matching: find.byType(RichText),
        ),
      ).text.style!;
    }

    await tester.pumpWidget(buildFrame());

    // Show the route which contains the banner.
    await tester.tap(find.text('push wrapped'));
    await tester.pumpAndSettle(); // route animation
    expect(bannerColor(), bannerBackgroundColor);
    expect(getTextStyle('hello').fontSize, bannerFontSize);
    expect(getTextStyle('hello').color, bannerTextColor);

    Navigator.of(navigatorContext)!.pop();
    await tester.pumpAndSettle(); // route animation

    await tester.tap(find.text('push unwrapped'));
    await tester.pumpAndSettle(); // route animation
    expect(bannerColor(), isNot(bannerBackgroundColor));
    expect(getTextStyle('hello').fontSize, isNot(bannerFontSize));
    expect(getTextStyle('hello').color, isNot(bannerTextColor));
  });

  testWidgets('DividerTheme.wrap()', (WidgetTester tester) async {
    const Color dividerColor = Color(0xFF0000FF);
    const double dividerSpace = 13;
    const double dividerThickness = 7;
    const Widget divider = Center(child: Divider());

    late BuildContext navigatorContext;

    Widget buildFrame() {
      return MaterialApp(
        home: Scaffold(
          body: DividerTheme(
            data: const DividerThemeData(
              color: dividerColor,
              space: dividerSpace,
              thickness: dividerThickness,
            ),
            child: Builder( // Introduce a context so the shadow DividerTheme is visible to captureAll().
              builder: (BuildContext context) {
                navigatorContext = context;
                return Center(
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      ElevatedButton(
                        child: const Text('push unwrapped'),
                        onPressed: () {
                          Navigator.of(context)!.push<void>(
                            MaterialPageRoute<void>(
                              // The Banner will see the default BannerTheme when built.
                              builder: (BuildContext _) => divider,
                            ),
                          );
                        },
                      ),
                      ElevatedButton(
                        child: const Text('push wrapped'),
                        onPressed: () {
                          Navigator.of(context)!.push<void>(
                            MaterialPageRoute<void>(
                              // Capture the shadow BannerTheme.
                              builder: (BuildContext _) => InheritedTheme.captureAll(context, divider),
                            ),
                          );
                        },
                      ),
                    ],
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    BorderSide dividerBorder() {
      final BoxDecoration decoration = tester.widget<Container>(
        find.descendant(of: find.byType(Divider), matching: find.byType(Container)).first,
      ).decoration! as BoxDecoration;
      return decoration.border!.bottom;
    }

    await tester.pumpWidget(buildFrame());

    // Show a route which contains a divider.
    await tester.tap(find.text('push wrapped'));
    await tester.pumpAndSettle(); // route animation
    expect(tester.getSize(find.byType(Divider)).height, dividerSpace);
    expect(dividerBorder().color, dividerColor);
    expect(dividerBorder().width, dividerThickness);

    Navigator.of(navigatorContext)!.pop();
    await tester.pumpAndSettle(); // route animation

    await tester.tap(find.text('push unwrapped'));
    await tester.pumpAndSettle(); // route animation
    expect(tester.getSize(find.byType(Divider)).height, isNot(dividerSpace));
    expect(dividerBorder().color, isNot(dividerColor));
    expect(dividerBorder().width, isNot(dividerThickness));
  });

  testWidgets('ListTileTheme.wrap()', (WidgetTester tester) async {
    const Color tileSelectedColor = Color(0xFF00FF00);
    const Color tileIconColor = Color(0xFF0000FF);
    const Color tileTextColor = Color(0xFFFF0000);

    final Key selectedIconKey = UniqueKey();
    final Key unselectedIconKey = UniqueKey();

    final Widget listTiles = Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            ListTile(
              leading: Icon(Icons.computer, key: selectedIconKey),
              title: const Text('selected'),
              enabled: true,
              selected: true,
            ),
            ListTile(
              leading: Icon(Icons.add, key: unselectedIconKey),
              title: const Text('unselected'),
              enabled: true,
              selected: false,
            ),
          ],
        ),
      ),
    );

    late BuildContext navigatorContext;

    Widget buildFrame() {
      return MaterialApp(
        home: Scaffold(
          body: ListTileTheme(
            selectedColor: tileSelectedColor,
            textColor: tileTextColor,
            iconColor: tileIconColor,
            child: Builder( // Introduce a context so the shadow ListTileTheme is visible to captureAll().
              builder: (BuildContext context) {
                navigatorContext = context;
                return Center(
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      ElevatedButton(
                        child: const Text('push unwrapped'),
                        onPressed: () {
                          Navigator.of(context)!.push<void>(
                            MaterialPageRoute<void>(
                              // The Banner will see the default BannerTheme when built.
                              builder: (BuildContext _) => listTiles,
                            ),
                          );
                        },
                      ),
                      ElevatedButton(
                        child: const Text('push wrapped'),
                        onPressed: () {
                          Navigator.of(context)!.push<void>(
                            MaterialPageRoute<void>(
                              // Capture the shadow BannerTheme.
                              builder: (BuildContext _) => InheritedTheme.captureAll(context, listTiles),
                            ),
                          );
                        },
                      ),
                    ],
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    TextStyle getTextStyle(String text) {
      return tester.widget<RichText>(
        find.descendant(of: find.text(text), matching: find.byType(RichText)),
      ).text.style!;
    }

    TextStyle getIconStyle(Key key) {
      return tester.widget<RichText>(
        find.descendant(
          of: find.byKey(key),
          matching: find.byType(RichText),
        ),
      ).text.style!;
    }

    await tester.pumpWidget(buildFrame());

    // Show a route which contains listTiles.
    await tester.tap(find.text('push wrapped'));
    await tester.pumpAndSettle(); // route animation
    expect(getTextStyle('unselected').color, tileTextColor);
    expect(getTextStyle('selected').color, tileSelectedColor);
    expect(getIconStyle(selectedIconKey).color, tileSelectedColor);
    expect(getIconStyle(unselectedIconKey).color, tileIconColor);

    Navigator.of(navigatorContext)!.pop();
    await tester.pumpAndSettle(); // route animation

    await tester.tap(find.text('push unwrapped'));
    await tester.pumpAndSettle(); // route animation
    expect(getTextStyle('unselected').color, isNot(tileTextColor));
    expect(getTextStyle('selected').color, isNot(tileSelectedColor));
    expect(getIconStyle(selectedIconKey).color, isNot(tileSelectedColor));
    expect(getIconStyle(unselectedIconKey).color, isNot(tileIconColor));
  });

  testWidgets('SliderTheme.wrap()', (WidgetTester tester) async {
    const Color activeTrackColor = Color(0xFF00FF00);
    const Color inactiveTrackColor = Color(0xFF0000FF);
    const Color thumbColor = Color(0xFFFF0000);

    final Widget slider = Scaffold(
      body: Center(
        child: Slider(
          value: 0.5,
          onChanged: (double value) { },
        ),
      ),
    );

    late BuildContext navigatorContext;

    Widget buildFrame() {
      return MaterialApp(
        home: Scaffold(
          body: SliderTheme(
            data: const SliderThemeData(
              activeTrackColor: activeTrackColor,
              inactiveTrackColor: inactiveTrackColor,
              thumbColor: thumbColor,
            ),
            child: Builder( // Introduce a context so the shadow SliderTheme is visible to captureAll().
              builder: (BuildContext context) {
                navigatorContext = context;
                return Center(
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      ElevatedButton(
                        child: const Text('push unwrapped'),
                        onPressed: () {
                          Navigator.of(context)!.push<void>(
                            MaterialPageRoute<void>(
                              // The slider will see the default SliderTheme when built.
                              builder: (BuildContext _) => slider,
                            ),
                          );
                        },
                      ),
                      ElevatedButton(
                        child: const Text('push wrapped'),
                        onPressed: () {
                          Navigator.of(context)!.push<void>(
                            MaterialPageRoute<void>(
                              // Capture the shadow SliderTheme.
                              builder: (BuildContext _) => InheritedTheme.captureAll(context, slider),
                            ),
                          );
                        },
                      ),
                    ],
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    await tester.pumpWidget(buildFrame());

    // Show a route which contains listTiles.
    await tester.tap(find.text('push wrapped'));
    await tester.pumpAndSettle(); // route animation
    RenderBox sliderBox = tester.firstRenderObject<RenderBox>(find.byType(Slider));
    expect(sliderBox, paints..rrect(color: activeTrackColor)..rrect(color: inactiveTrackColor));
    expect(sliderBox, paints..circle(color: thumbColor));

    Navigator.of(navigatorContext)!.pop();
    await tester.pumpAndSettle(); // route animation

    await tester.tap(find.text('push unwrapped'));
    await tester.pumpAndSettle(); // route animation
    sliderBox = tester.firstRenderObject<RenderBox>(find.byType(Slider));
    expect(sliderBox, isNot(paints..rrect(color: activeTrackColor)..rrect(color: inactiveTrackColor)));
    expect(sliderBox, isNot(paints..circle(color: thumbColor)));
  });

  testWidgets('ToggleButtonsTheme.wrap()', (WidgetTester tester) async {
    const Color buttonColor = Color(0xFF00FF00);
    const Color selectedButtonColor = Color(0xFFFF0000);

    final Widget toggleButtons = Scaffold(
      body: Center(
        child: ToggleButtons(
          children: const <Widget>[
            Text('selected'),
            Text('unselected'),
          ],
          isSelected: const <bool>[true, false],
          onPressed: (int index) { },
        ),
      ),
    );

    late BuildContext navigatorContext;

    Widget buildFrame() {
      return MaterialApp(
        home: Scaffold(
          body: ToggleButtonsTheme(
            data: const ToggleButtonsThemeData(
              color: buttonColor,
              selectedColor: selectedButtonColor,
            ),
            child: Builder( // Introduce a context so the shadow ToggleButtonsTheme is visible to captureAll().
              builder: (BuildContext context) {
                navigatorContext = context;
                return Center(
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      ElevatedButton(
                        child: const Text('push unwrapped'),
                        onPressed: () {
                          Navigator.of(context)!.push<void>(
                            MaterialPageRoute<void>(
                              // The slider will see the default ToggleButtonsTheme when built.
                              builder: (BuildContext _) => toggleButtons,
                            ),
                          );
                        },
                      ),
                      ElevatedButton(
                        child: const Text('push wrapped'),
                        onPressed: () {
                          Navigator.of(context)!.push<void>(
                            MaterialPageRoute<void>(
                              // Capture the shadow toggleButtons.
                              builder: (BuildContext _) => InheritedTheme.captureAll(context, toggleButtons),
                            ),
                          );
                        },
                      ),
                    ],
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    Color getTextColor(String text) {
      return tester.widget<RichText>(
        find.descendant(of: find.text(text), matching: find.byType(RichText)),
      ).text.style!.color!;
    }

    await tester.pumpWidget(buildFrame());

    // Show a route which contains toggleButtons.
    await tester.tap(find.text('push wrapped'));
    await tester.pumpAndSettle(); // route animation
    expect(getTextColor('selected'), selectedButtonColor);
    expect(getTextColor('unselected'), buttonColor);

    Navigator.of(navigatorContext)!.pop();
    await tester.pumpAndSettle(); // route animation

    await tester.tap(find.text('push unwrapped'));
    await tester.pumpAndSettle(); // route animation
    expect(getTextColor('selected'), isNot(selectedButtonColor));
    expect(getTextColor('unselected'), isNot(buttonColor));

  });

  testWidgets('ButtonTheme.wrap()', (WidgetTester tester) async {
    const Color buttonColor = Color(0xFF00FF00);
    const Color disabledButtonColor = Color(0xFFFF0000);

    final Widget buttons = Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            const RaisedButton(child: Text('disabled'), onPressed: null),
            RaisedButton(child: const Text('enabled'), onPressed: () { }),
          ],
        ),
      ),
    );

    late BuildContext navigatorContext;

    Widget buildFrame() {
      return MaterialApp(
        home: Scaffold(
          body: ButtonTheme.fromButtonThemeData(
            data: const ButtonThemeData(
              buttonColor: buttonColor,
              disabledColor: disabledButtonColor,
            ),
            child: Builder( // Introduce a context so the shadow ButtonTheme is visible to captureAll().
              builder: (BuildContext context) {
                navigatorContext = context;
                return Center(
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      RaisedButton(
                        child: const Text('push unwrapped'),
                        onPressed: () {
                          Navigator.of(context)!.push<void>(
                            MaterialPageRoute<void>(
                              // The slider will see the default ButtonTheme when built.
                              builder: (BuildContext _) => buttons,
                            ),
                          );
                        },
                      ),
                      RaisedButton(
                        child: const Text('push wrapped'),
                        onPressed: () {
                          Navigator.of(context)!.push<void>(
                            MaterialPageRoute<void>(
                              // Capture the shadow toggleButtons.
                              builder: (BuildContext _) => InheritedTheme.captureAll(context, buttons),
                            ),
                          );
                        },
                      ),
                    ],
                  ),
                );
              },
            ),
          ),
        ),
      );
    }

    Color getButtonColor(String text) {
      return tester.widget<Material>(
        find.descendant(
          of: find.widgetWithText(RawMaterialButton, text),
          matching: find.byType(Material),
        ),
      ).color!;
    }

    await tester.pumpWidget(buildFrame());

    // Show a route which contains toggleButtons.
    await tester.tap(find.text('push wrapped'));
    await tester.pumpAndSettle(); // route animation
    expect(getButtonColor('disabled'), disabledButtonColor);
    expect(getButtonColor('enabled'), buttonColor);

    Navigator.of(navigatorContext)!.pop();
    await tester.pumpAndSettle(); // route animation

    await tester.tap(find.text('push unwrapped'));
    await tester.pumpAndSettle(); // route animation
    expect(getButtonColor('disabled'), isNot(disabledButtonColor));
    expect(getButtonColor('enabled'), isNot(buttonColor));

  });

}
