// Copyright 2019 The Flutter team. 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_gen/gen_l10n/gallery_localizations.dart';
import 'package:gallery/demos/material/material_demo_types.dart';

enum SimpleValue {
  one,
  two,
  three,
}

enum CheckedValue {
  one,
  two,
  three,
  four,
}

class MenuDemo extends StatefulWidget {
  const MenuDemo({super.key, required this.type});

  final MenuDemoType type;

  @override
  State<MenuDemo> createState() => _MenuDemoState();
}

class _MenuDemoState extends State<MenuDemo> {
  void showInSnackBar(String value) {
    ScaffoldMessenger.of(context).hideCurrentSnackBar();
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Text(value),
    ));
  }

  @override
  Widget build(BuildContext context) {
    Widget demo;
    switch (widget.type) {
      case MenuDemoType.contextMenu:
        demo = _ContextMenuDemo(showInSnackBar: showInSnackBar);
        break;
      case MenuDemoType.sectionedMenu:
        demo = _SectionedMenuDemo(showInSnackBar: showInSnackBar);
        break;
      case MenuDemoType.simpleMenu:
        demo = _SimpleMenuDemo(showInSnackBar: showInSnackBar);
        break;
      case MenuDemoType.checklistMenu:
        demo = _ChecklistMenuDemo(showInSnackBar: showInSnackBar);
        break;
    }

    return Scaffold(
      appBar: AppBar(
        title: Text(GalleryLocalizations.of(context)!.demoMenuTitle),
        automaticallyImplyLeading: false,
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 20),
        child: Center(
          child: demo,
        ),
      ),
    );
  }
}

// BEGIN menuDemoContext

// 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.
class _ContextMenuDemo extends StatelessWidget {
  const _ContextMenuDemo({required this.showInSnackBar});

  final void Function(String value) showInSnackBar;

  @override
  Widget build(BuildContext context) {
    final localizations = GalleryLocalizations.of(context)!;
    return ListTile(
      title: Text(localizations.demoMenuAnItemWithAContextMenuButton),
      trailing: PopupMenuButton<String>(
        padding: EdgeInsets.zero,
        onSelected: (value) => showInSnackBar(
          localizations.demoMenuSelected(value),
        ),
        itemBuilder: (context) => <PopupMenuItem<String>>[
          PopupMenuItem<String>(
            value: localizations.demoMenuContextMenuItemOne,
            child: Text(
              localizations.demoMenuContextMenuItemOne,
            ),
          ),
          PopupMenuItem<String>(
            enabled: false,
            child: Text(
              localizations.demoMenuADisabledMenuItem,
            ),
          ),
          PopupMenuItem<String>(
            value: localizations.demoMenuContextMenuItemThree,
            child: Text(
              localizations.demoMenuContextMenuItemThree,
            ),
          ),
        ],
      ),
    );
  }
}

// END

// BEGIN menuDemoSectioned

// 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.
class _SectionedMenuDemo extends StatelessWidget {
  const _SectionedMenuDemo({required this.showInSnackBar});

  final void Function(String value) showInSnackBar;

  @override
  Widget build(BuildContext context) {
    final localizations = GalleryLocalizations.of(context)!;
    return ListTile(
      title: Text(localizations.demoMenuAnItemWithASectionedMenu),
      trailing: PopupMenuButton<String>(
        padding: EdgeInsets.zero,
        onSelected: (value) =>
            showInSnackBar(localizations.demoMenuSelected(value)),
        itemBuilder: (context) => <PopupMenuEntry<String>>[
          PopupMenuItem<String>(
            value: localizations.demoMenuPreview,
            child: ListTile(
              leading: const Icon(Icons.visibility),
              title: Text(
                localizations.demoMenuPreview,
              ),
            ),
          ),
          PopupMenuItem<String>(
            value: localizations.demoMenuShare,
            child: ListTile(
              leading: const Icon(Icons.person_add),
              title: Text(
                localizations.demoMenuShare,
              ),
            ),
          ),
          PopupMenuItem<String>(
            value: localizations.demoMenuGetLink,
            child: ListTile(
              leading: const Icon(Icons.link),
              title: Text(
                localizations.demoMenuGetLink,
              ),
            ),
          ),
          const PopupMenuDivider(),
          PopupMenuItem<String>(
            value: localizations.demoMenuRemove,
            child: ListTile(
              leading: const Icon(Icons.delete),
              title: Text(
                localizations.demoMenuRemove,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

// END

// BEGIN menuDemoSimple

// 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.
class _SimpleMenuDemo extends StatefulWidget {
  const _SimpleMenuDemo({required this.showInSnackBar});

  final void Function(String value) showInSnackBar;

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

class _SimpleMenuDemoState extends State<_SimpleMenuDemo> {
  late SimpleValue _simpleValue;

  void showAndSetMenuSelection(BuildContext context, SimpleValue value) {
    setState(() {
      _simpleValue = value;
    });
    widget.showInSnackBar(
      GalleryLocalizations.of(context)!
          .demoMenuSelected(simpleValueToString(context, value)),
    );
  }

  String simpleValueToString(BuildContext context, SimpleValue value) {
    final localizations = GalleryLocalizations.of(context)!;
    return {
      SimpleValue.one: localizations.demoMenuItemValueOne,
      SimpleValue.two: localizations.demoMenuItemValueTwo,
      SimpleValue.three: localizations.demoMenuItemValueThree,
    }[value]!;
  }

  @override
  void initState() {
    super.initState();
    _simpleValue = SimpleValue.two;
  }

  @override
  Widget build(BuildContext context) {
    return PopupMenuButton<SimpleValue>(
      padding: EdgeInsets.zero,
      initialValue: _simpleValue,
      onSelected: (value) => showAndSetMenuSelection(context, value),
      itemBuilder: (context) => <PopupMenuItem<SimpleValue>>[
        PopupMenuItem<SimpleValue>(
          value: SimpleValue.one,
          child: Text(simpleValueToString(
            context,
            SimpleValue.one,
          )),
        ),
        PopupMenuItem<SimpleValue>(
          value: SimpleValue.two,
          child: Text(simpleValueToString(
            context,
            SimpleValue.two,
          )),
        ),
        PopupMenuItem<SimpleValue>(
          value: SimpleValue.three,
          child: Text(simpleValueToString(
            context,
            SimpleValue.three,
          )),
        ),
      ],
      child: ListTile(
        title: Text(
            GalleryLocalizations.of(context)!.demoMenuAnItemWithASimpleMenu),
        subtitle: Text(simpleValueToString(context, _simpleValue)),
      ),
    );
  }
}

// END

// BEGIN menuDemoChecklist

// Pressing the PopupMenuButton on the right of this item shows a menu
// whose items have checked icons that reflect this app's state.
class _ChecklistMenuDemo extends StatefulWidget {
  const _ChecklistMenuDemo({required this.showInSnackBar});

  final void Function(String value) showInSnackBar;

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

class _RestorableCheckedValues extends RestorableProperty<Set<CheckedValue>> {
  Set<CheckedValue> _checked = <CheckedValue>{};

  void check(CheckedValue value) {
    _checked.add(value);
    notifyListeners();
  }

  void uncheck(CheckedValue value) {
    _checked.remove(value);
    notifyListeners();
  }

  bool isChecked(CheckedValue value) => _checked.contains(value);

  Iterable<String> checkedValuesToString(BuildContext context) {
    final localizations = GalleryLocalizations.of(context)!;
    return _checked.map((value) {
      return {
        CheckedValue.one: localizations.demoMenuOne,
        CheckedValue.two: localizations.demoMenuTwo,
        CheckedValue.three: localizations.demoMenuThree,
        CheckedValue.four: localizations.demoMenuFour,
      }[value]!;
    });
  }

  @override
  Set<CheckedValue> createDefaultValue() => _checked;

  @override
  Set<CheckedValue> initWithValue(Set<CheckedValue> a) {
    _checked = a;
    return _checked;
  }

  @override
  Object toPrimitives() => _checked.map((value) => value.index).toList();

  @override
  Set<CheckedValue> fromPrimitives(Object? data) {
    final checkedValues = data as List<dynamic>;
    return Set.from(checkedValues.map<CheckedValue>((dynamic id) {
      return CheckedValue.values[id as int];
    }));
  }
}

class _ChecklistMenuDemoState extends State<_ChecklistMenuDemo>
    with RestorationMixin {
  final _RestorableCheckedValues _checkedValues = _RestorableCheckedValues()
    ..check(CheckedValue.three);

  @override
  String get restorationId => 'checklist_menu_demo';

  @override
  void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
    registerForRestoration(_checkedValues, 'checked_values');
  }

  void showCheckedMenuSelections(BuildContext context, CheckedValue value) {
    if (_checkedValues.isChecked(value)) {
      setState(() {
        _checkedValues.uncheck(value);
      });
    } else {
      setState(() {
        _checkedValues.check(value);
      });
    }

    widget.showInSnackBar(
      GalleryLocalizations.of(context)!.demoMenuChecked(
        _checkedValues.checkedValuesToString(context),
      ),
    );
  }

  String checkedValueToString(BuildContext context, CheckedValue value) {
    final localizations = GalleryLocalizations.of(context)!;
    return {
      CheckedValue.one: localizations.demoMenuOne,
      CheckedValue.two: localizations.demoMenuTwo,
      CheckedValue.three: localizations.demoMenuThree,
      CheckedValue.four: localizations.demoMenuFour,
    }[value]!;
  }

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

  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(
        GalleryLocalizations.of(context)!.demoMenuAnItemWithAChecklistMenu,
      ),
      trailing: PopupMenuButton<CheckedValue>(
        padding: EdgeInsets.zero,
        onSelected: (value) => showCheckedMenuSelections(context, value),
        itemBuilder: (context) => <PopupMenuItem<CheckedValue>>[
          CheckedPopupMenuItem<CheckedValue>(
            value: CheckedValue.one,
            checked: _checkedValues.isChecked(CheckedValue.one),
            child: Text(
              checkedValueToString(context, CheckedValue.one),
            ),
          ),
          CheckedPopupMenuItem<CheckedValue>(
            value: CheckedValue.two,
            enabled: false,
            checked: _checkedValues.isChecked(CheckedValue.two),
            child: Text(
              checkedValueToString(context, CheckedValue.two),
            ),
          ),
          CheckedPopupMenuItem<CheckedValue>(
            value: CheckedValue.three,
            checked: _checkedValues.isChecked(CheckedValue.three),
            child: Text(
              checkedValueToString(context, CheckedValue.three),
            ),
          ),
          CheckedPopupMenuItem<CheckedValue>(
            value: CheckedValue.four,
            checked: _checkedValues.isChecked(CheckedValue.four),
            child: Text(
              checkedValueToString(context, CheckedValue.four),
            ),
          ),
        ],
      ),
    );
  }
}

// END
