// 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/services.dart';

void main() {
  runApp(
    const MaterialApp(
      title: 'Menu Tester',
      home: Material(
        child: Home(),
      ),
    ),
  );
}

class Home extends StatefulWidget {
  const Home({super.key});

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  final MenuController _controller = MenuController();
  VisualDensity _density = VisualDensity.standard;
  TextDirection _textDirection = TextDirection.ltr;
  double _extraPadding = 0;
  bool _addItem = false;
  bool _accelerators = true;
  bool _transparent = false;
  bool _funkyTheme = false;

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    MenuThemeData menuTheme = MenuTheme.of(context);
    MenuBarThemeData menuBarTheme = MenuBarTheme.of(context);
    MenuButtonThemeData menuButtonTheme = MenuButtonTheme.of(context);
    if (_funkyTheme) {
      menuTheme = const MenuThemeData(
        style: MenuStyle(
          shape: MaterialStatePropertyAll<OutlinedBorder>(
            RoundedRectangleBorder(
              borderRadius: BorderRadius.all(
                Radius.circular(10),
              ),
            ),
          ),
          backgroundColor: MaterialStatePropertyAll<Color?>(Colors.blue),
          elevation: MaterialStatePropertyAll<double?>(10),
          padding: MaterialStatePropertyAll<EdgeInsetsDirectional>(
            EdgeInsetsDirectional.all(20),
          ),
        ),
      );
      menuButtonTheme = const MenuButtonThemeData(
        style: ButtonStyle(
          shape: MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder()),
          backgroundColor: MaterialStatePropertyAll<Color?>(Colors.green),
          foregroundColor: MaterialStatePropertyAll<Color?>(Colors.white),
        ),
      );
      menuBarTheme = const MenuBarThemeData(
        style: MenuStyle(
          shape: MaterialStatePropertyAll<OutlinedBorder>(RoundedRectangleBorder()),
          backgroundColor: MaterialStatePropertyAll<Color?>(Colors.blue),
          elevation: MaterialStatePropertyAll<double?>(10),
          padding: MaterialStatePropertyAll<EdgeInsetsDirectional>(
            EdgeInsetsDirectional.all(20),
          ),
        ),
      );
    }
    return SafeArea(
      child: Padding(
        padding: EdgeInsets.all(_extraPadding),
        child: Directionality(
          textDirection: _textDirection,
          child: Theme(
            data: theme.copyWith(
              visualDensity: _density,
              menuTheme: _transparent
                  ? MenuThemeData(
                      style: MenuStyle(
                        backgroundColor: MaterialStatePropertyAll<Color>(
                          Colors.blue.withOpacity(0.12),
                        ),
                        elevation: const MaterialStatePropertyAll<double>(0),
                      ),
                    )
                  : menuTheme,
              menuBarTheme: menuBarTheme,
              menuButtonTheme: menuButtonTheme,
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                _TestMenus(
                  menuController: _controller,
                  accelerators: _accelerators,
                  addItem: _addItem,
                ),
                Expanded(
                  child: SingleChildScrollView(
                    child: _Controls(
                      menuController: _controller,
                      density: _density,
                      addItem: _addItem,
                      accelerators: _accelerators,
                      transparent: _transparent,
                      funkyTheme: _funkyTheme,
                      extraPadding: _extraPadding,
                      textDirection: _textDirection,
                      onDensityChanged: (VisualDensity value) {
                        setState(() {
                          _density = value;
                        });
                      },
                      onTextDirectionChanged: (TextDirection value) {
                        setState(() {
                          _textDirection = value;
                        });
                      },
                      onExtraPaddingChanged: (double value) {
                        setState(() {
                          _extraPadding = value;
                        });
                      },
                      onAddItemChanged: (bool value) {
                        setState(() {
                          _addItem = value;
                        });
                      },
                      onAcceleratorsChanged: (bool value) {
                        setState(() {
                          _accelerators = value;
                        });
                      },
                      onTransparentChanged: (bool value) {
                        setState(() {
                          _transparent = value;
                        });
                      },
                      onFunkyThemeChanged: (bool value) {
                        setState(() {
                          _funkyTheme = value;
                        });
                      },
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class _Controls extends StatefulWidget {
  const _Controls({
    required this.density,
    required this.textDirection,
    required this.extraPadding,
    this.addItem = false,
    this.accelerators = true,
    this.transparent = false,
    this.funkyTheme = false,
    required this.onDensityChanged,
    required this.onTextDirectionChanged,
    required this.onExtraPaddingChanged,
    required this.onAddItemChanged,
    required this.onAcceleratorsChanged,
    required this.onTransparentChanged,
    required this.onFunkyThemeChanged,
    required this.menuController,
  });

  final VisualDensity density;
  final TextDirection textDirection;
  final double extraPadding;
  final bool addItem;
  final bool accelerators;
  final bool transparent;
  final bool funkyTheme;
  final ValueChanged<VisualDensity> onDensityChanged;
  final ValueChanged<TextDirection> onTextDirectionChanged;
  final ValueChanged<double> onExtraPaddingChanged;
  final ValueChanged<bool> onAddItemChanged;
  final ValueChanged<bool> onAcceleratorsChanged;
  final ValueChanged<bool> onTransparentChanged;
  final ValueChanged<bool> onFunkyThemeChanged;
  final MenuController menuController;

  @override
  State<_Controls> createState() => _ControlsState();
}

class _ControlsState extends State<_Controls> {
  final FocusNode _focusNode = FocusNode(debugLabel: 'Floating');

  @override
  void dispose() {
    _focusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            MenuAnchor(
              childFocusNode: _focusNode,
              style: const MenuStyle(alignment: AlignmentDirectional.topEnd),
              alignmentOffset: const Offset(100, -8),
              menuChildren: <Widget>[
                MenuItemButton(
                  shortcut: TestMenu.standaloneMenu1.shortcut,
                  onPressed: () {
                    _itemSelected(TestMenu.standaloneMenu1);
                  },
                  child: MenuAcceleratorLabel(TestMenu.standaloneMenu1.label),
                ),
                MenuItemButton(
                  leadingIcon: const Icon(Icons.send),
                  trailingIcon: const Icon(Icons.mail),
                  onPressed: () {
                    _itemSelected(TestMenu.standaloneMenu2);
                  },
                  child: MenuAcceleratorLabel(TestMenu.standaloneMenu2.label),
                ),
              ],
              builder: (BuildContext context, MenuController controller, Widget? child) {
                return TextButton(
                  focusNode: _focusNode,
                  onPressed: () {
                    if (controller.isOpen) {
                      controller.close();
                    } else {
                      controller.open();
                    }
                  },
                  child: child!,
                );
              },
              child: const MenuAcceleratorLabel('Open Menu'),
            ),
            ConstrainedBox(
              constraints: const BoxConstraints(maxWidth: 400),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: <Widget>[
                  _ControlSlider(
                    label: 'Extra Padding: ${widget.extraPadding.toStringAsFixed(1)}',
                    value: widget.extraPadding,
                    max: 40,
                    divisions: 20,
                    onChanged: (double value) {
                      widget.onExtraPaddingChanged(value);
                    },
                  ),
                  _ControlSlider(
                    label: 'Horizontal Density: ${widget.density.horizontal.toStringAsFixed(1)}',
                    value: widget.density.horizontal,
                    max: 4,
                    min: -4,
                    divisions: 12,
                    onChanged: (double value) {
                      widget.onDensityChanged(
                        VisualDensity(
                          horizontal: value,
                          vertical: widget.density.vertical,
                        ),
                      );
                    },
                  ),
                  _ControlSlider(
                    label: 'Vertical Density: ${widget.density.vertical.toStringAsFixed(1)}',
                    value: widget.density.vertical,
                    max: 4,
                    min: -4,
                    divisions: 12,
                    onChanged: (double value) {
                      widget.onDensityChanged(
                        VisualDensity(
                          horizontal: widget.density.horizontal,
                          vertical: value,
                        ),
                      );
                    },
                  ),
                ],
              ),
            ),
            Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Row(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    Checkbox(
                      value: widget.textDirection == TextDirection.rtl,
                      onChanged: (bool? value) {
                        if (value ?? false) {
                          widget.onTextDirectionChanged(TextDirection.rtl);
                        } else {
                          widget.onTextDirectionChanged(TextDirection.ltr);
                        }
                      },
                    ),
                    const Text('RTL Text')
                  ],
                ),
                Row(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    Checkbox(
                      value: widget.addItem,
                      onChanged: (bool? value) {
                        if (value ?? false) {
                          widget.onAddItemChanged(true);
                        } else {
                          widget.onAddItemChanged(false);
                        }
                      },
                    ),
                    const Text('Add Item')
                  ],
                ),
                Row(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    Checkbox(
                      value: widget.accelerators,
                      onChanged: (bool? value) {
                        if (value ?? false) {
                          widget.onAcceleratorsChanged(true);
                        } else {
                          widget.onAcceleratorsChanged(false);
                        }
                      },
                    ),
                    const Text('Enable Accelerators')
                  ],
                ),
                Row(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    Checkbox(
                      value: widget.transparent,
                      onChanged: (bool? value) {
                        if (value ?? false) {
                          widget.onTransparentChanged(true);
                        } else {
                          widget.onTransparentChanged(false);
                        }
                      },
                    ),
                    const Text('Transparent')
                  ],
                ),
                Row(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    Checkbox(
                      value: widget.funkyTheme,
                      onChanged: (bool? value) {
                        if (value ?? false) {
                          widget.onFunkyThemeChanged(true);
                        } else {
                          widget.onFunkyThemeChanged(false);
                        }
                      },
                    ),
                    const Text('Funky Theme')
                  ],
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  void _itemSelected(TestMenu item) {
    debugPrint('App: Selected item ${item.label}');
  }
}

class _ControlSlider extends StatelessWidget {
  const _ControlSlider({
    required this.label,
    required this.value,
    required this.onChanged,
    this.min = 0,
    this.max = 1,
    this.divisions,
  });

  final String label;
  final double value;
  final ValueChanged<double> onChanged;
  final double min;
  final double max;
  final int? divisions;

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.end,
      children: <Widget>[
        Container(
          alignment: AlignmentDirectional.centerEnd,
          constraints: const BoxConstraints(minWidth: 150),
          child: Text(label),
        ),
        Expanded(
          child: Slider(
            value: value,
            min: min,
            max: max,
            divisions: divisions,
            onChanged: onChanged,
          ),
        ),
      ],
    );
  }
}

class _TestMenus extends StatefulWidget {
  const _TestMenus({
    required this.menuController,
    this.addItem = false,
    this.accelerators = false,
  });

  final MenuController menuController;
  final bool addItem;
  final bool accelerators;

  @override
  State<_TestMenus> createState() => _TestMenusState();
}

class _TestMenusState extends State<_TestMenus> {
  final TextEditingController textController = TextEditingController();
  bool? checkboxState = false;
  TestMenu? radioValue;
  ShortcutRegistryEntry? _shortcutsEntry;

  void _itemSelected(TestMenu item) {
    debugPrint('App: Selected item ${item.label}');
  }

  void _openItem(TestMenu item) {
    debugPrint('App: Opened item ${item.label}');
  }

  void _closeItem(TestMenu item) {
    debugPrint('App: Closed item ${item.label}');
  }

  void _setRadio(TestMenu? item) {
    debugPrint('App: Set Radio item ${item?.label}');
    setState(() {
      radioValue = item;
    });
  }

  void _setCheck(TestMenu item) {
    debugPrint('App: Set Checkbox item ${item.label}');
    setState(() {
      checkboxState = switch (checkboxState) {
        false => true,
        true  => null,
        null  => false,
      };
    });
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _shortcutsEntry?.dispose();
    final Map<ShortcutActivator, Intent> shortcuts = <ShortcutActivator, Intent>{};
    for (final TestMenu item in TestMenu.values) {
      if (item.shortcut == null) {
        continue;
      }
      switch (item) {
        case TestMenu.radioMenu1:
        case TestMenu.radioMenu2:
        case TestMenu.radioMenu3:
          shortcuts[item.shortcut!] = VoidCallbackIntent(() => _setRadio(item));
        case TestMenu.subMenu1:
          shortcuts[item.shortcut!] = VoidCallbackIntent(() => _setCheck(item));
        case TestMenu.mainMenu1:
        case TestMenu.mainMenu2:
        case TestMenu.mainMenu3:
        case TestMenu.mainMenu4:
        case TestMenu.subMenu2:
        case TestMenu.subMenu3:
        case TestMenu.subMenu4:
        case TestMenu.subMenu5:
        case TestMenu.subMenu6:
        case TestMenu.subMenu7:
        case TestMenu.subMenu8:
        case TestMenu.subSubMenu1:
        case TestMenu.subSubMenu2:
        case TestMenu.subSubMenu3:
        case TestMenu.subSubSubMenu1:
        case TestMenu.testButton:
        case TestMenu.standaloneMenu1:
        case TestMenu.standaloneMenu2:
          shortcuts[item.shortcut!] = VoidCallbackIntent(() => _itemSelected(item));
      }
    }
    _shortcutsEntry = ShortcutRegistry.of(context).addAll(shortcuts);
  }

  @override
  void dispose() {
    _shortcutsEntry?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        Expanded(
          child: MenuBar(
            controller: widget.menuController,
            children: createTestMenus(
              onPressed: _itemSelected,
              onOpen: _openItem,
              onClose: _closeItem,
              onCheckboxChanged: (TestMenu menu, bool? value) {
                _setCheck(menu);
              },
              onRadioChanged: _setRadio,
              checkboxValue: checkboxState,
              radioValue: radioValue,
              menuController: widget.menuController,
              textEditingController: textController,
              includeExtraGroups: widget.addItem,
              accelerators: widget.accelerators,
            ),
          ),
        ),
      ],
    );
  }
}

List<Widget> createTestMenus({
  void Function(TestMenu)? onPressed,
  void Function(TestMenu, bool?)? onCheckboxChanged,
  void Function(TestMenu?)? onRadioChanged,
  void Function(TestMenu)? onOpen,
  void Function(TestMenu)? onClose,
  Map<TestMenu, MenuSerializableShortcut> shortcuts = const <TestMenu, MenuSerializableShortcut>{},
  bool? checkboxValue,
  TestMenu? radioValue,
  MenuController? menuController,
  TextEditingController? textEditingController,
  bool includeExtraGroups = false,
  bool accelerators = false,
}) {
  Widget submenuButton(
    TestMenu menu, {
    required List<Widget> menuChildren,
  }) {
    return SubmenuButton(
      onOpen: onOpen != null ? () => onOpen(menu) : null,
      onClose: onClose != null ? () => onClose(menu) : null,
      menuChildren: menuChildren,
      child: accelerators ? MenuAcceleratorLabel(menu.acceleratorLabel) : Text(menu.label),
    );
  }

  Widget menuItemButton(
    TestMenu menu, {
    bool enabled = true,
    Widget? leadingIcon,
    Widget? trailingIcon,
    Key? key,
  }) {
    return MenuItemButton(
      key: key,
      onPressed: enabled && onPressed != null ? () => onPressed(menu) : null,
      shortcut: shortcuts[menu],
      leadingIcon: leadingIcon,
      trailingIcon: trailingIcon,
      child: accelerators ? MenuAcceleratorLabel(menu.acceleratorLabel) : Text(menu.label),
    );
  }

  Widget checkboxMenuButton(
    TestMenu menu, {
    bool enabled = true,
    bool tristate = false,
    Widget? leadingIcon,
    Widget? trailingIcon,
    Key? key,
  }) {
    return CheckboxMenuButton(
      key: key,
      value: checkboxValue,
      tristate: tristate,
      onChanged: enabled && onCheckboxChanged != null ? (bool? value) => onCheckboxChanged(menu, value) : null,
      shortcut: menu.shortcut,
      trailingIcon: trailingIcon,
      child: accelerators ? MenuAcceleratorLabel(menu.acceleratorLabel) : Text(menu.label),
    );
  }

  Widget radioMenuButton(
    TestMenu menu, {
    bool enabled = true,
    bool toggleable = false,
    Widget? leadingIcon,
    Widget? trailingIcon,
    Key? key,
  }) {
    return RadioMenuButton<TestMenu>(
      key: key,
      groupValue: radioValue,
      value: menu,
      toggleable: toggleable,
      onChanged: enabled && onRadioChanged != null ? onRadioChanged : null,
      shortcut: menu.shortcut,
      trailingIcon: trailingIcon,
      child: accelerators ? MenuAcceleratorLabel(menu.acceleratorLabel) : Text(menu.label),
    );
  }

  final List<Widget> result = <Widget>[
    submenuButton(
      TestMenu.mainMenu1,
      menuChildren: <Widget>[
        checkboxMenuButton(
          TestMenu.subMenu1,
          tristate: true,
          trailingIcon: const Icon(Icons.assessment),
        ),
        radioMenuButton(
          TestMenu.radioMenu1,
          toggleable: true,
          trailingIcon: const Icon(Icons.assessment),
        ),
        radioMenuButton(
          TestMenu.radioMenu2,
          toggleable: true,
          trailingIcon: const Icon(Icons.assessment),
        ),
        radioMenuButton(
          TestMenu.radioMenu3,
          toggleable: true,
          trailingIcon: const Icon(Icons.assessment),
        ),
        menuItemButton(
          TestMenu.subMenu2,
          leadingIcon: const Icon(Icons.send),
          trailingIcon: const Icon(Icons.mail),
        ),
      ],
    ),
    submenuButton(
      TestMenu.mainMenu2,
      menuChildren: <Widget>[
        MenuAcceleratorCallbackBinding(
          onInvoke: onPressed != null
              ? () {
                  onPressed.call(TestMenu.testButton);
                  menuController?.close();
                }
              : null,
          child: TextButton(
            onPressed: onPressed != null
                ? () {
                    onPressed.call(TestMenu.testButton);
                    menuController?.close();
                  }
                : null,
            child: accelerators
                ? MenuAcceleratorLabel(TestMenu.testButton.acceleratorLabel)
                : Text(TestMenu.testButton.label),
          ),
        ),
        menuItemButton(TestMenu.subMenu3),
      ],
    ),
    submenuButton(
      TestMenu.mainMenu3,
      menuChildren: <Widget>[
        menuItemButton(TestMenu.subMenu8),
        MenuItemButton(
          onPressed: () {
            debugPrint('Focused Item: $primaryFocus');
          },
          child: const Text('Print Focused Item'),
        )
      ],
    ),
    submenuButton(
      TestMenu.mainMenu4,
      menuChildren: <Widget>[
        MenuItemButton(
          onPressed: () {
            debugPrint('Activated text input item with ${textEditingController?.text} as a value.');
          },
          child: SizedBox(
            width: 200,
            child: TextField(
              controller: textEditingController,
              onSubmitted: (String value) {
                debugPrint('String $value submitted.');
              },
            ),
          ),
        ),
        submenuButton(
          TestMenu.subMenu5,
          menuChildren: <Widget>[
            menuItemButton(TestMenu.subSubMenu1),
            menuItemButton(TestMenu.subSubMenu2),
            if (includeExtraGroups)
              submenuButton(
                TestMenu.subSubMenu3,
                menuChildren: <Widget>[
                  for (int i=0; i < 100; ++i)
                    MenuItemButton(
                      onPressed: () {},
                      child: Text('Menu Item $i'),
                    ),
                ],
              ),
          ],
        ),
        menuItemButton(TestMenu.subMenu6, enabled: false),
        menuItemButton(TestMenu.subMenu7),
        menuItemButton(TestMenu.subMenu7),
        menuItemButton(TestMenu.subMenu8),
      ],
    ),
  ];
  return result;
}

enum TestMenu {
  mainMenu1('Menu 1'),
  mainMenu2('M&enu &2'),
  mainMenu3('Me&nu &3'),
  mainMenu4('Men&u &4'),
  radioMenu1('Radio Menu One', SingleActivator(LogicalKeyboardKey.digit1, control: true)),
  radioMenu2('Radio Menu Two', SingleActivator(LogicalKeyboardKey.digit2, control: true)),
  radioMenu3('Radio Menu Three', SingleActivator(LogicalKeyboardKey.digit3, control: true)),
  subMenu1('Sub Menu &1', SingleActivator(LogicalKeyboardKey.keyB, control: true)),
  subMenu2('Sub Menu &2'),
  subMenu3('Sub Menu &3', SingleActivator(LogicalKeyboardKey.enter, control: true)),
  subMenu4('Sub Menu &4'),
  subMenu5('Sub Menu &5'),
  subMenu6('Sub Menu &6', SingleActivator(LogicalKeyboardKey.tab, control: true)),
  subMenu7('Sub Menu &7'),
  subMenu8('Sub Menu &8'),
  subSubMenu1('Sub Sub Menu &1', SingleActivator(LogicalKeyboardKey.f10, control: true)),
  subSubMenu2('Sub Sub Menu &2'),
  subSubMenu3('Sub Sub Menu &3'),
  subSubSubMenu1('Sub Sub Sub Menu &1', SingleActivator(LogicalKeyboardKey.f11, control: true)),
  testButton('&TEST && &&& Button &'),
  standaloneMenu1('Standalone Menu &1', SingleActivator(LogicalKeyboardKey.keyC, control: true)),
  standaloneMenu2('Standalone Menu &2');

  const TestMenu(this.acceleratorLabel, [this.shortcut]);
  final MenuSerializableShortcut? shortcut;
  final String acceleratorLabel;
  // Strip the accelerator markers.
  String get label => MenuAcceleratorLabel.stripAcceleratorMarkers(acceleratorLabel);
}
