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

class MenuDemo extends StatefulWidget {
  const MenuDemo({ Key? key }) : super(key: key);

  static const String routeName = '/material/menu';

  @override
  MenuDemoState createState() => MenuDemoState();
}

class MenuDemoState extends State<MenuDemo> {

  final String _simpleValue1 = 'Menu item value one';
  final String _simpleValue2 = 'Menu item value two';
  final String _simpleValue3 = 'Menu item value three';
  String? _simpleValue;

  final String _checkedValue1 = 'One';
  final String _checkedValue2 = 'Two';
  final String _checkedValue3 = 'Free';
  final String _checkedValue4 = 'Four';
  late List<String> _checkedValues;

  @override
  void initState() {
    super.initState();
    _simpleValue = _simpleValue2;
    _checkedValues = <String>[_checkedValue3];
  }

  void showInSnackBar(String value) {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
     content: Text(value),
    ));
  }

  void showMenuSelection(String value) {
    if (<String>[_simpleValue1, _simpleValue2, _simpleValue3].contains(value))
      setState(() => _simpleValue = value);
    showInSnackBar('You selected: $value');
  }

  void showCheckedMenuSelections(String value) {
    if (_checkedValues.contains(value))
      _checkedValues.remove(value);
    else
      _checkedValues.add(value);

    showInSnackBar('Checked $_checkedValues');
  }

  bool isChecked(String value) => _checkedValues.contains(value);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Menus'),
        actions: <Widget>[
          MaterialDemoDocumentationButton(MenuDemo.routeName),
          PopupMenuButton<String>(
            onSelected: showMenuSelection,
            itemBuilder: (BuildContext context) => <PopupMenuItem<String>>[
              const PopupMenuItem<String>(
                value: 'Toolbar menu',
                child: Text('Toolbar menu'),
              ),
              const PopupMenuItem<String>(
                value: 'Right here',
                child: Text('Right here'),
              ),
              const PopupMenuItem<String>(
                value: 'Hooray!',
                child: Text('Hooray!'),
              ),
            ],
          ),
        ],
      ),
      body: ListTileTheme(
        iconColor: Theme.of(context).brightness == Brightness.light
            ? Colors.grey[600]
            : Colors.grey[500],
        child: ListView(
          padding: kMaterialListPadding,
          children: <Widget>[
            // Pressing the PopupMenuButton on the right of this item shows
            // a simple menu with one disabled item. Typically the contents
            // of this "contextual menu" would reflect the app's state.
            ListTile(
              title: const Text('An item with a context menu button'),
              trailing: PopupMenuButton<String>(
                padding: EdgeInsets.zero,
                onSelected: showMenuSelection,
                itemBuilder: (BuildContext context) => <PopupMenuItem<String>>[
                  PopupMenuItem<String>(
                    value: _simpleValue1,
                    child: const Text('Context menu item one'),
                  ),
                  const PopupMenuItem<String>(
                    enabled: false,
                    child: Text('A disabled menu item'),
                  ),
                  PopupMenuItem<String>(
                    value: _simpleValue3,
                    child: const Text('Context menu item three'),
                  ),
                ],
              ),
            ),
            // Pressing the PopupMenuButton on the right of this item shows
            // a menu whose items have text labels and icons and a divider
            // That separates the first three items from the last one.
            ListTile(
              title: const Text('An item with a sectioned menu'),
              trailing: PopupMenuButton<String>(
                padding: EdgeInsets.zero,
                onSelected: showMenuSelection,
                itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
                  const PopupMenuItem<String>(
                    value: 'Preview',
                    child: ListTile(
                      leading: Icon(Icons.visibility),
                      title: Text('Preview'),
                    ),
                  ),
                  const PopupMenuItem<String>(
                    value: 'Share',
                    child: ListTile(
                      leading: Icon(Icons.person_add),
                      title: Text('Share'),
                    ),
                  ),
                  const PopupMenuItem<String>(
                    value: 'Get Link',
                    child: ListTile(
                      leading: Icon(Icons.link),
                      title: Text('Get link'),
                    ),
                  ),
                  const PopupMenuDivider(),
                  const PopupMenuItem<String>(
                    value: 'Remove',
                    child: ListTile(
                      leading: Icon(Icons.delete),
                      title: Text('Remove'),
                    ),
                  ),
                ],
              ),
            ),
            // This entire list item is a PopupMenuButton. Tapping anywhere shows
            // a menu whose current value is highlighted and aligned over the
            // list item's center line.
            PopupMenuButton<String>(
              padding: EdgeInsets.zero,
              initialValue: _simpleValue,
              onSelected: showMenuSelection,
              child: ListTile(
                title: const Text('An item with a simple menu'),
                subtitle: Text(_simpleValue!),
              ),
              itemBuilder: (BuildContext context) => <PopupMenuItem<String>>[
                PopupMenuItem<String>(
                  value: _simpleValue1,
                  child: Text(_simpleValue1),
                ),
                PopupMenuItem<String>(
                  value: _simpleValue2,
                  child: Text(_simpleValue2),
                ),
                PopupMenuItem<String>(
                  value: _simpleValue3,
                  child: Text(_simpleValue3),
                ),
              ],
            ),
            // Pressing the PopupMenuButton on the right of this item shows a menu
            // whose items have checked icons that reflect this app's state.
            ListTile(
              title: const Text('An item with a checklist menu'),
              trailing: PopupMenuButton<String>(
                padding: EdgeInsets.zero,
                onSelected: showCheckedMenuSelections,
                itemBuilder: (BuildContext context) => <PopupMenuItem<String>>[
                  CheckedPopupMenuItem<String>(
                    value: _checkedValue1,
                    checked: isChecked(_checkedValue1),
                    child: Text(_checkedValue1),
                  ),
                  CheckedPopupMenuItem<String>(
                    value: _checkedValue2,
                    enabled: false,
                    checked: isChecked(_checkedValue2),
                    child: Text(_checkedValue2),
                  ),
                  CheckedPopupMenuItem<String>(
                    value: _checkedValue3,
                    checked: isChecked(_checkedValue3),
                    child: Text(_checkedValue3),
                  ),
                  CheckedPopupMenuItem<String>(
                    value: _checkedValue4,
                    checked: isChecked(_checkedValue4),
                    child: Text(_checkedValue4),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
