import 'package:comunic/helpers/account_helper.dart';
import 'package:comunic/helpers/server_config_helper.dart';
import 'package:comunic/models/new_account.dart';
import 'package:comunic/ui/widgets/new_password_input_widget.dart';
import 'package:comunic/utils/input_utils.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

/// Create account route
///
/// @author Pierre HUBERT

class CreateAccountRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(tr("Create an account")),
      ),
      body: _CreateAccountRouteBody(),
    );
  }
}

class _CreateAccountRouteBody extends StatefulWidget {
  @override
  __CreateAccountRouteBodyState createState() =>
      __CreateAccountRouteBodyState();
}

class __CreateAccountRouteBodyState extends State<_CreateAccountRouteBody> {
  final _firstNameController = TextEditingController();
  final _lastNameController = TextEditingController();
  final _emailController = TextEditingController();
  final _passwordInputKey = GlobalKey<NewPasswordInputWidgetState>();
  final _verifyPasswordController = TextEditingController();
  bool _acceptedTOS = false;

  bool _isCreating = false;
  CreateAccountResult _createAccountResult;

  bool _showErrors = false;

  bool get _isFirstNameValid => _firstNameController.text.length > 3;

  bool get _isLastNameValid => _lastNameController.text.length > 3;

  bool get _isEmailValid => validateEmail(_emailController.text);

  bool get _isPasswordValid => _passwordInputKey.currentState.valid;

  bool get _isPasswordConfirmationValid =>
      _passwordInputKey.currentState != null &&
      _passwordInputKey.currentState.value == _verifyPasswordController.text;

  bool get _isFormValid =>
      _isFirstNameValid &&
      _isLastNameValid &&
      _isEmailValid &&
      _isPasswordValid &&
      _isPasswordConfirmationValid &&
      _acceptedTOS;

  String get errorMessage => _createAccountResult ==
          CreateAccountResult.ERROR_EXISTING_EMAIL
      ? tr("An account is already associated to this email address!")
      : _createAccountResult == CreateAccountResult.ERROR_TOO_MANY_REQUESTS
          ? tr(
              "Too many accounts have been created from this IP address for now. Please try again later.")
          : tr(
              "An error occurred while creating your account. Please try again.");

  @override
  Widget build(BuildContext context) {
    if (_isCreating)
      return Center(
        child: CircularProgressIndicator(),
      );

    return Center(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: ConstrainedBox(
          constraints: BoxConstraints(maxWidth: 370),
          child: ListView(
            children: <Widget>[
              _createAccountResult != null
                  ? buildErrorCard(errorMessage)
                  : Container(),

              // First name
              _InputEntry(
                controller: _firstNameController,
                label: tr("First name"),
                onEdited: _updateUI,
                icon: Icon(Icons.perm_identity),
                error: _showErrors && !_isFirstNameValid
                    ? tr("Invalid first name!")
                    : null,
              ),

              // Last name
              _InputEntry(
                controller: _lastNameController,
                label: tr("Last name"),
                onEdited: _updateUI,
                icon: Icon(Icons.perm_identity),
                error: _showErrors && !_isLastNameValid
                    ? tr("Invalid last name!")
                    : null,
              ),

              // Email address
              _InputEntry(
                controller: _emailController,
                label: tr("Email address"),
                onEdited: _updateUI,
                icon: Icon(Icons.email),
                keyboard: TextInputType.emailAddress,
                error: _showErrors && !_isEmailValid
                    ? tr("Invalid email address!")
                    : null,
              ),

              // Password
              NewPasswordInputWidget(
                key: _passwordInputKey,
                label: tr("Password"),
                onEdited: _updateUI,
                icon: Icon(Icons.lock),
                user: UserInfoForPassword(
                  firstName: _firstNameController.text,
                  lastName: _lastNameController.text,
                  email: _emailController.text,
                ),
              ),

              // Verify password
              _InputEntry(
                controller: _verifyPasswordController,
                label: tr("Confirm your password"),
                onEdited: _updateUI,
                icon: Icon(Icons.lock_outline),
                isPassword: true,
                error: _showErrors && !_isPasswordConfirmationValid
                    ? tr("The password and its confirmation do not match!")
                    : null,
              ),

              // TOS
              CheckboxListTile(
                title:
                    Text(tr("I have read and accepted the Terms Of Service.")),
                value: _acceptedTOS,
                onChanged: (b) {
                  _acceptedTOS = b;
                  _updateUI();
                },
                subtitle: _showErrors && !_acceptedTOS
                    ? Text(
                        tr("You must accept the Terms Of Service to continue."),
                        style: TextStyle(color: Colors.redAccent),
                      )
                    : null,
                controlAffinity: ListTileControlAffinity.leading,
                secondary: IconButton(
                  icon: Icon(Icons.open_in_new),
                  onPressed: _openTOS,
                ),
              ),

              // Submit button
              Center(
                child: ElevatedButton(
                  onPressed: _submitForm,
                  child: Text("Submit"),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  void _updateUI() {
    setState(() {
      // Nothing yet
    });
  }

  void _submitForm() async {
    if (!_isFormValid) {
      _showErrors = true;
      _updateUI();
      return;
    }

    setState(() {
      _isCreating = true;
    });

    final result = await AccountHelper().createAccount(NewAccount(
      firstName: _firstNameController.text,
      lastName: _lastNameController.text,
      email: _emailController.text,
      password: _passwordInputKey.currentState.value,
    ));

    setState(() {
      _isCreating = false;
    });

    if (result != CreateAccountResult.SUCCESS) {
      _createAccountResult = result;
      _showCreateAccountError();
      _updateUI();
      return;
    }

    _accountCreated();
  }

  void _openTOS() => launch(ServerConfigurationHelper.config.termsURL);

  void _showCreateAccountError() async {
    await showCupertinoDialog(
      context: context,
      builder: (c) => CupertinoAlertDialog(
        title: Text(tr("Error while creating your account")),
        content: Text(errorMessage),
        actions: <Widget>[
          CupertinoButton(
            child: Text(tr("Ok").toUpperCase()),
            onPressed: () => Navigator.of(context).pop(),
          )
        ],
      ),
    );
  }

  void _accountCreated() async {
    await showCupertinoDialog(
      context: context,
      builder: (c) => CupertinoAlertDialog(
        title: Text(tr("Account created")),
        content: Text(tr(
            "Your account has been successfully created. You can now login to start to use it.")),
        actions: <Widget>[
          CupertinoButton(
              child: Text(tr("Login")), onPressed: () => Navigator.of(c).pop())
        ],
      ),
    );

    Navigator.of(context).pop();
  }
}

class _InputEntry extends StatelessWidget {
  final TextEditingController controller;
  final String label;
  final VoidCallback onEdited;
  final bool isPassword;
  final String error;
  final Widget icon;
  final TextInputType keyboard;

  const _InputEntry({
    Key key,
    @required this.controller,
    @required this.label,
    @required this.onEdited,
    this.isPassword = false,
    this.error,
    this.icon,
    this.keyboard,
  })  : assert(controller != null),
        assert(label != null),
        assert(onEdited != null),
        assert(isPassword != null),
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: controller,
      onChanged: (s) => onEdited(),
      keyboardType: keyboard,
      obscureText: isPassword,
      decoration: InputDecoration(
        alignLabelWithHint: true,
        errorText: error,
        labelText: label,
        icon: icon,
      ),
    );
  }
}