import '../state/app_state.dart';
import '../ui/adaptive.dart'
    show AdaptiveDialogAction, AppScaffold, isPlatformAndroid;
import 'package:pb_authenticator_totp/totp_algorithm.dart';
import 'package:pb_authenticator_totp/totp.dart' show Base32, TotpItem;
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import '../l10n/app_localizations.dart';
import 'package:provider/provider.dart';

/// Page for adding accounts.
class AddPage extends StatefulWidget {
  const AddPage({super.key});

  @override
  State<AddPage> createState() => _AddPageState();
}

class _AddPageState extends State<AddPage> {
  // Uniquely identify Form widget for validation
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  // Text field controllers
  final _issuerController = TextEditingController();
  final _accountNameController = TextEditingController();
  final _secretController = TextEditingController();

  // Value of dropdown fields
  int _digits = 6;
  int _period = 30;

  @override
  void initState() {
    super.initState();

    // Add listener to secret controller
    _secretController.addListener(_enableSecretAutoValidation);
  }

  // Enable validation when text is changed (but don't validate initially)
  bool _secretAutoValidation = false;
  void _enableSecretAutoValidation() {
    if (_secretController.text.isEmpty) return;
    _secretController.removeListener(_enableSecretAutoValidation);
    setState(() {
      _secretAutoValidation = true;
    });
  }

  @override
  dispose() {
    _issuerController.dispose();
    _accountNameController.dispose();
    _secretController.dispose();
    super.dispose();
  }

  // Adds item or display errors
  void addItem(TotpItem item) {
    try {
      Provider.of<AppState>(context, listen: false).addItem(item).then((_) {
        Navigator.pop(context);
      });
    } catch (e) {
      // TODO: Fix exception handling
      var errMessage = e.toString();
      if (e.toString().contains('DUPLICATE_ACCOUNT')) {
        errMessage = AppLocalizations.of(context)!.errDuplicateAccount;
      } else if (e.toString().contains('ID_COLLISION')) {
        errMessage = AppLocalizations.of(context)!.errIdCollision;
      }

      showAdaptiveDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog.adaptive(
                title: Text(AppLocalizations.of(context)!.error),
                content: Text(errMessage),
                actions: [
                  AdaptiveDialogAction(
                      onPressed: Navigator.of(context).pop,
                      child: Text(AppLocalizations.of(context)!.ok))
                ]);
          });
    }
  }

  /// Whether the secret field is valid
  bool secretFieldValid() {
    return _secretController.text.isNotEmpty &&
        Base32.isBase32(_secretController.text);
  }

  // Handle add action
  void handleAdd() {
    // Validate
    if (!_formKey.currentState!.validate()) {
      return;
    }

    // No iOS validator, so may need to recheck and fail
    if (!secretFieldValid()) {
      showCupertinoDialog(
        context: context,
        builder: (BuildContext context) {
          return CupertinoAlertDialog(
            title: Text(AppLocalizations.of(context)!.error),
            content: Text(AppLocalizations.of(context)!.secretInvalidMessage),
            actions: [
              CupertinoDialogAction(
                  onPressed: Navigator.of(context).pop,
                  child: Text(AppLocalizations.of(context)!.ok))
            ],
          );
        },
      );
      return;
    }

    // Initialise and add TOTP item
    var item = TotpItem(
        _secretController.text,
        _digits,
        _period,
        OtpHashAlgorithm.sha1,
        _issuerController.text,
        _accountNameController.text);

    addItem(item);
  }

  // Separates fields
  // Adapted from flutter examples
  static const BorderSide _greyBorder = BorderSide(
    color: CupertinoColors.lightBackgroundGray,
    style: BorderStyle.solid,
    width: 0.0,
  );
  static const _boxDecoration = BoxDecoration(
      border: Border(
          bottom: _greyBorder,
          top: _greyBorder,
          left: BorderSide.none,
          right: BorderSide.none));

  @override
  Widget build(BuildContext context) {
    return AppScaffold(
      title: Text(AppLocalizations.of(context)!.addTitle),
      cupertinoNavigationBar: CupertinoNavigationBar(
          middle: Text(AppLocalizations.of(context)!.addTitle),
          trailing: CupertinoButton(
              padding: const EdgeInsets.all(0),
              onPressed: handleAdd,
              child: Text(AppLocalizations.of(context)!.add))),
      body: Form(
        key: _formKey,
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 15),
          child: ListView(
            children: isPlatformAndroid()
                ? <Widget>[
                    // Key
                    TextFormField(
                      controller: _secretController,
                      textCapitalization: TextCapitalization.characters,
                      autocorrect: false,
                      autovalidateMode: _secretAutoValidation
                          ? AutovalidateMode.onUserInteraction
                          : AutovalidateMode.disabled,
                      validator: (value) => secretFieldValid()
                          ? null
                          : AppLocalizations.of(context)!.secretInvalidMessage,
                      decoration: InputDecoration(
                          labelText: AppLocalizations.of(context)!.secret),
                    ),
                    // Provider
                    TextFormField(
                      controller: _issuerController,
                      textCapitalization: TextCapitalization.words,
                      decoration: InputDecoration(
                          labelText: AppLocalizations.of(context)!.issuer,
                          hintText: 'Example Service'),
                    ),

                    // Account name
                    TextFormField(
                      controller: _accountNameController,
                      keyboardType: TextInputType.emailAddress,
                      decoration: InputDecoration(
                          labelText: AppLocalizations.of(context)!.accountName,
                          hintText: 'user@example.com'),
                    ),

                    // # of digits
                    InputDecorator(
                      decoration: InputDecoration(
                        contentPadding: const EdgeInsets.only(top: 15),
                        labelText: AppLocalizations.of(context)!.digits,
                        border: InputBorder.none,
                        labelStyle: const TextStyle(fontSize: 20),
                      ),
                      child: DropdownButton(
                        value: _digits,
                        onChanged: (value) {
                          setState(() {
                            _digits = value;
                          });
                        },
                        isExpanded: true,
                        items: const <DropdownMenuItem>[
                          DropdownMenuItem(value: 6, child: Text("6")),
                          DropdownMenuItem(value: 8, child: Text("8")),
                        ],
                      ),
                    ),

                    // Time step
                    InputDecorator(
                      decoration: InputDecoration(
                          contentPadding: const EdgeInsets.only(top: 10),
                          labelText: AppLocalizations.of(context)!.period,
                          border: InputBorder.none,
                          labelStyle: const TextStyle(fontSize: 20)),
                      child: DropdownButton(
                        value: _period,
                        onChanged: (value) {
                          setState(() {
                            _period = value;
                          });
                        },
                        isExpanded: true,
                        items: const <DropdownMenuItem>[
                          DropdownMenuItem(value: 30, child: Text("30")),
                          DropdownMenuItem(value: 60, child: Text("60")),
                        ],
                      ),
                    ),

                    // Add button
                    Padding(
                      padding: const EdgeInsets.symmetric(vertical: 5),
                      child: ElevatedButton(
                        onPressed: handleAdd,
                        child: Text(AppLocalizations.of(context)!.add),
                      ),
                    )
                  ]
                : <Widget>[
                    // Key
                    CupertinoTextField(
                        controller: _secretController,
                        textCapitalization: TextCapitalization.characters,
                        autocorrect: false,
                        decoration: _boxDecoration,
                        padding: const EdgeInsets.symmetric(vertical: 15),
                        prefix: Text(AppLocalizations.of(context)!.secret),
                        textAlign: TextAlign.right),

                    // Provider
                    CupertinoTextField(
                        controller: _issuerController,
                        textCapitalization: TextCapitalization.words,
                        decoration: _boxDecoration,
                        padding: const EdgeInsets.symmetric(vertical: 15),
                        prefix: Text(AppLocalizations.of(context)!.issuer),
                        textAlign: TextAlign.right),

                    // Account name
                    CupertinoTextField(
                        controller: _accountNameController,
                        keyboardType: TextInputType.emailAddress,
                        decoration: _boxDecoration,
                        padding: const EdgeInsets.symmetric(vertical: 15),
                        prefix: Text(AppLocalizations.of(context)!.accountName),
                        textAlign: TextAlign.right),

                    // # of digits
                    Container(
                      padding: const EdgeInsets.symmetric(vertical: 15),
                      decoration: _boxDecoration,
                      child: ListBody(
                        children: [
                          Padding(
                              padding: const EdgeInsets.only(bottom: 8),
                              child:
                                  Text(AppLocalizations.of(context)!.digits)),
                          CupertinoSegmentedControl(
                            groupValue: _digits.toString(),
                            children: const {'6': Text('6'), '8': Text('8')},
                            onValueChanged: (v) {
                              setState(() {
                                _digits = int.parse(v);
                              });
                            },
                          )
                        ],
                      ),
                    ),

                    // Time step
                    Container(
                      padding: const EdgeInsets.symmetric(vertical: 15),
                      decoration: _boxDecoration,
                      child: ListBody(
                        children: [
                          Padding(
                              padding: const EdgeInsets.only(bottom: 8),
                              child:
                                  Text(AppLocalizations.of(context)!.period)),
                          CupertinoSegmentedControl(
                            groupValue: _period.toString(),
                            children: const {
                              '30': Text('30'),
                              '60': Text('60')
                            },
                            onValueChanged: (v) {
                              setState(() {
                                _period = int.parse(v);
                              });
                            },
                          )
                        ],
                      ),
                    ),

                    // Add button
                    Container()
                  ],
          ),
        ),
      ),
    );
  }
}
