// Copyright 2013 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:adaptive_dialog/adaptive_dialog.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

import 'shared/data.dart';

void main() => runApp(App());

/// The main app.
class App extends StatelessWidget {
  /// Creates an [App].
  App({Key? key}) : super(key: key);

  /// The title of the app.
  static const String title = 'GoRouter Example: Navigator Integration';

  @override
  Widget build(BuildContext context) => MaterialApp.router(
        routeInformationProvider: _router.routeInformationProvider,
        routeInformationParser: _router.routeInformationParser,
        routerDelegate: _router.routerDelegate,
        title: title,
        debugShowCheckedModeBanner: false,
      );

  late final GoRouter _router = GoRouter(
    routes: <GoRoute>[
      GoRoute(
        name: 'home',
        path: '/',
        builder: (BuildContext context, GoRouterState state) =>
            HomeScreen(families: Families.data),
        routes: <GoRoute>[
          GoRoute(
            name: 'family',
            path: 'family/:fid',
            builder: (BuildContext context, GoRouterState state) =>
                FamilyScreenWithAdd(
              family: Families.family(state.params['fid']!),
            ),
            routes: <GoRoute>[
              GoRoute(
                name: 'person',
                path: 'person/:pid',
                builder: (BuildContext context, GoRouterState state) {
                  final Family family = Families.family(state.params['fid']!);
                  final Person person = family.person(state.params['pid']!);
                  return PersonScreen(family: family, person: person);
                },
              ),
              GoRoute(
                name: 'new-person',
                path: 'new-person',
                builder: (BuildContext context, GoRouterState state) {
                  final Family family = Families.family(state.params['fid']!);
                  return NewPersonScreen2(family: family);
                },
              ),
            ],
          ),
        ],
      ),
    ],
  );
}

/// The home screen that shows a list of families.
class HomeScreen extends StatelessWidget {
  /// Creates a [HomeScreen].
  const HomeScreen({required this.families, Key? key}) : super(key: key);

  /// The list of families.
  final List<Family> families;

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(title: const Text(App.title)),
        body: ListView(
          children: <Widget>[
            for (final Family f in families)
              ListTile(
                title: Text(f.name),
                onTap: () => context
                    .goNamed('family', params: <String, String>{'fid': f.id}),
              )
          ],
        ),
      );
}

/// The family screen.
class FamilyScreenWithAdd extends StatefulWidget {
  /// Creates a [FamilyScreenWithAdd].
  const FamilyScreenWithAdd({required this.family, Key? key}) : super(key: key);

  /// The family to display.
  final Family family;

  @override
  State<FamilyScreenWithAdd> createState() => _FamilyScreenWithAddState();
}

class _FamilyScreenWithAddState extends State<FamilyScreenWithAdd> {
  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: Text(widget.family.name),
          actions: <Widget>[
            IconButton(
              // onPressed: () => _addPerson1(context), // Navigator-style
              onPressed: () => _addPerson2(context), // GoRouter-style
              tooltip: 'Add Person',
              icon: const Icon(Icons.add),
            ),
          ],
        ),
        body: ListView(
          children: <Widget>[
            for (final Person p in widget.family.people)
              ListTile(
                title: Text(p.name),
                onTap: () => context.go(context.namedLocation(
                  'person',
                  params: <String, String>{
                    'fid': widget.family.id,
                    'pid': p.id
                  },
                  queryParams: <String, String>{'qid': 'quid'},
                )),
              ),
          ],
        ),
      );

  // using a Navigator and a Navigator result
  // ignore: unused_element
  Future<void> _addPerson1(BuildContext context) async {
    final Person? person = await Navigator.push<Person>(
      context,
      MaterialPageRoute<Person>(
        builder: (BuildContext context) =>
            NewPersonScreen1(family: widget.family),
      ),
    );

    if (person != null) {
      setState(() => widget.family.people.add(person));

      // ignore: use_build_context_synchronously
      context.goNamed('person', params: <String, String>{
        'fid': widget.family.id,
        'pid': person.id,
      });
    }
  }

  // using a GoRouter page
  void _addPerson2(BuildContext context) {
    context.goNamed('new-person',
        params: <String, String>{'fid': widget.family.id});
  }
}

/// The person screen.
class PersonScreen extends StatelessWidget {
  /// Creates a [PersonScreen].
  const PersonScreen({required this.family, required this.person, Key? key})
      : super(key: key);

  /// The family this person belong to.
  final Family family;

  /// The person to be displayed.
  final Person person;

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(title: Text(person.name)),
        body: Text('${person.name} ${family.name} is ${person.age} years old'),
      );
}

// returning a Navigator result
/// The screen to add a new person into the family.
class NewPersonScreen1 extends StatefulWidget {
  /// Creates a [NewPersonScreen1].
  const NewPersonScreen1({required this.family, Key? key}) : super(key: key);

  /// The family to be added to.
  final Family family;

  @override
  State<NewPersonScreen1> createState() => _NewPersonScreen1State();
}

class _NewPersonScreen1State extends State<NewPersonScreen1> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final TextEditingController _nameController = TextEditingController();
  final TextEditingController _ageController = TextEditingController();

  @override
  void dispose() {
    super.dispose();
    _nameController.dispose();
    _ageController.dispose();
  }

  @override
  Widget build(BuildContext context) => WillPopScope(
        // ask the user if they'd like to adandon their data
        onWillPop: () async => abandonNewPerson(context),
        child: Scaffold(
          appBar: AppBar(
            title: Text('New person for family ${widget.family.name}'),
          ),
          body: Form(
            key: _formKey,
            child: Center(
              child: SizedBox(
                width: 400,
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    TextFormField(
                      controller: _nameController,
                      decoration: const InputDecoration(labelText: 'name'),
                      validator: (String? value) =>
                          value == null || value.isEmpty
                              ? 'Please enter a name'
                              : null,
                    ),
                    TextFormField(
                      controller: _ageController,
                      decoration: const InputDecoration(labelText: 'age'),
                      validator: (String? value) => value == null ||
                              value.isEmpty ||
                              int.tryParse(value) == null
                          ? 'Please enter an age'
                          : null,
                    ),
                    ButtonBar(children: <Widget>[
                      TextButton(
                        onPressed: () async {
                          // ask the user if they'd like to adandon their data
                          if (await abandonNewPerson(context)) {
                            Navigator.pop(context);
                          }
                        },
                        child: const Text('Cancel'),
                      ),
                      ElevatedButton(
                        onPressed: () {
                          if (_formKey.currentState!.validate()) {
                            final Person person = Person(
                              id: 'p${widget.family.people.length + 1}',
                              name: _nameController.text,
                              age: int.parse(_ageController.text),
                            );

                            Navigator.pop(context, person);
                          }
                        },
                        child: const Text('Create'),
                      ),
                    ]),
                  ],
                ),
              ),
            ),
          ),
        ),
      );

  Future<bool> abandonNewPerson(BuildContext context) async {
    final OkCancelResult result = await showOkCancelAlertDialog(
      context: context,
      title: 'Abandon New Person',
      message: 'Are you sure you abandon this new person?',
      okLabel: 'Keep',
      cancelLabel: 'Abandon',
    );

    return result == OkCancelResult.cancel;
  }
}

// adding the result to the data directly (GoRouter page)
/// The screen to add a new person into the family.
class NewPersonScreen2 extends StatefulWidget {
  /// Creates a [NewPersonScreen1].
  const NewPersonScreen2({required this.family, Key? key}) : super(key: key);

  /// The family to display.
  final Family family;

  @override
  State<NewPersonScreen2> createState() => _NewPersonScreen2State();
}

class _NewPersonScreen2State extends State<NewPersonScreen2> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final TextEditingController _nameController = TextEditingController();
  final TextEditingController _ageController = TextEditingController();

  @override
  void dispose() {
    super.dispose();
    _nameController.dispose();
    _ageController.dispose();
  }

  @override
  Widget build(BuildContext context) => WillPopScope(
        // ask the user if they'd like to adandon their data
        onWillPop: () async => abandonNewPerson(context),
        child: Scaffold(
          appBar: AppBar(
            title: Text('New person for family ${widget.family.name}'),
          ),
          body: Form(
            key: _formKey,
            child: Center(
              child: SizedBox(
                width: 400,
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    TextFormField(
                      controller: _nameController,
                      decoration: const InputDecoration(labelText: 'name'),
                      validator: (String? value) =>
                          value == null || value.isEmpty
                              ? 'Please enter a name'
                              : null,
                    ),
                    TextFormField(
                      controller: _ageController,
                      decoration: const InputDecoration(labelText: 'age'),
                      validator: (String? value) => value == null ||
                              value.isEmpty ||
                              int.tryParse(value) == null
                          ? 'Please enter an age'
                          : null,
                    ),
                    ButtonBar(children: <Widget>[
                      TextButton(
                        onPressed: () async {
                          // ask the user if they'd like to adandon their data
                          if (await abandonNewPerson(context)) {
                            // Navigator.pop(context) would work here, too
                            context.pop();
                          }
                        },
                        child: const Text('Cancel'),
                      ),
                      ElevatedButton(
                        onPressed: () {
                          if (_formKey.currentState!.validate()) {
                            final Person person = Person(
                              id: 'p${widget.family.people.length + 1}',
                              name: _nameController.text,
                              age: int.parse(_ageController.text),
                            );

                            widget.family.people.add(person);

                            context.goNamed('person', params: <String, String>{
                              'fid': widget.family.id,
                              'pid': person.id,
                            });
                          }
                        },
                        child: const Text('Create'),
                      ),
                    ]),
                  ],
                ),
              ),
            ),
          ),
        ),
      );

  Future<bool> abandonNewPerson(BuildContext context) async {
    final OkCancelResult result = await showOkCancelAlertDialog(
      context: context,
      title: 'Abandon New Person',
      message: 'Are you sure you abandon this new person?',
      okLabel: 'Keep',
      cancelLabel: 'Abandon',
    );

    return result == OkCancelResult.cancel;
  }
}
