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

enum DialogDemoAction {
  cancel,
  discard,
  disagree,
  agree,
}

const String _alertWithoutTitleText = 'Discard draft?';

const String _alertWithTitleText =
  'Let Google help apps determine location. This means sending anonymous location '
  'data to Google, even when no apps are running.';

class DialogDemoItem extends StatelessWidget {
  const DialogDemoItem({ super.key, this.icon, this.color, this.text, this.onPressed });

  final IconData? icon;
  final Color? color;
  final String? text;
  final VoidCallback? onPressed;

  @override
  Widget build(BuildContext context) {
    return SimpleDialogOption(
      onPressed: onPressed,
      child: Row(
        children: <Widget>[
          Icon(icon, size: 36.0, color: color),
          Padding(
            padding: const EdgeInsets.only(left: 16.0),
            child: Text(text!),
          ),
        ],
      ),
    );
  }
}

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

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

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

class DialogDemoState extends State<DialogDemo> {

  TimeOfDay? _selectedTime;

  @override
  void initState() {
    super.initState();
    final DateTime now = DateTime.now();
    _selectedTime = TimeOfDay(hour: now.hour, minute: now.minute);
  }

  void showDemoDialog<T>({ required BuildContext context, Widget? child }) {
    showDialog<T>(
      context: context,
      builder: (BuildContext context) => child!,
    )
    .then((T? value) { // The value passed to Navigator.pop() or null.
      if (value != null) {
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(
          content: Text('You selected: $value'),
        ));
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);
    final TextStyle dialogTextStyle = theme.textTheme.subtitle1!.copyWith(color: theme.textTheme.caption!.color);

    return Scaffold(
      appBar: AppBar(
        title: const Text('Dialogs'),
        actions: <Widget>[MaterialDemoDocumentationButton(DialogDemo.routeName)],
      ),
      body: ListView(
        padding: const EdgeInsets.symmetric(vertical: 24.0, horizontal: 72.0),
        children: <Widget>[
          ElevatedButton(
            child: const Text('ALERT'),
            onPressed: () {
              showDemoDialog<DialogDemoAction>(
                context: context,
                child: AlertDialog(
                  content: Text(
                    _alertWithoutTitleText,
                    style: dialogTextStyle,
                  ),
                  actions: <Widget>[
                    TextButton(
                      child: const Text('CANCEL'),
                      onPressed: () { Navigator.pop(context, DialogDemoAction.cancel); },
                    ),
                    TextButton(
                      child: const Text('DISCARD'),
                      onPressed: () { Navigator.pop(context, DialogDemoAction.discard); },
                    ),
                  ],
                ),
              );
            },
          ),
          ElevatedButton(
            child: const Text('ALERT WITH TITLE'),
            onPressed: () {
              showDemoDialog<DialogDemoAction>(
                context: context,
                child: AlertDialog(
                  title: const Text("Use Google's location service?"),
                  content: Text(
                    _alertWithTitleText,
                    style: dialogTextStyle,
                  ),
                  actions: <Widget>[
                    TextButton(
                      child: const Text('DISAGREE'),
                      onPressed: () { Navigator.pop(context, DialogDemoAction.disagree); },
                    ),
                    TextButton(
                      child: const Text('AGREE'),
                      onPressed: () { Navigator.pop(context, DialogDemoAction.agree); },
                    ),
                  ],
                ),
              );
            },
          ),
          ElevatedButton(
            child: const Text('SIMPLE'),
            onPressed: () {
              showDemoDialog<String>(
                context: context,
                child: SimpleDialog(
                  title: const Text('Set backup account'),
                  children: <Widget>[
                    DialogDemoItem(
                      icon: Icons.account_circle,
                      color: theme.primaryColor,
                      text: 'username@gmail.com',
                      onPressed: () { Navigator.pop(context, 'username@gmail.com'); },
                    ),
                    DialogDemoItem(
                      icon: Icons.account_circle,
                      color: theme.primaryColor,
                      text: 'user02@gmail.com',
                      onPressed: () { Navigator.pop(context, 'user02@gmail.com'); },
                    ),
                    DialogDemoItem(
                      icon: Icons.add_circle,
                      text: 'add account',
                      color: theme.disabledColor,
                    ),
                  ],
                ),
              );
            },
          ),
          ElevatedButton(
            child: const Text('CONFIRMATION'),
            onPressed: () {
              showTimePicker(
                context: context,
                initialTime: _selectedTime!,
              )
              .then((TimeOfDay? value) {
                if (value != null && value != _selectedTime) {
                  _selectedTime = value;
                  ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                    content: Text('You selected: ${value.format(context)}'),
                  ));
                }
              });
            },
          ),
          ElevatedButton(
            child: const Text('FULLSCREEN'),
            onPressed: () {
              Navigator.push(context, MaterialPageRoute<DismissDialogAction>(
                builder: (BuildContext context) => const FullScreenDialogDemo(),
                fullscreenDialog: true,
              ));
            },
          ),
        ]
        // Add a little space between the buttons
        .map<Widget>((Widget button) {
          return Container(
            padding: const EdgeInsets.symmetric(vertical: 8.0),
            child: button,
          );
        })
        .toList(),
      ),
    );
  }
}
