import 'package:comunic/helpers/settings_helper.dart';
import 'package:comunic/helpers/users_helper.dart';
import 'package:comunic/lists/custom_emojies_list.dart';
import 'package:comunic/models/custom_emoji.dart';
import 'package:comunic/models/new_emoji.dart';
import 'package:comunic/models/user.dart';
import 'package:comunic/ui/widgets/async_screen_widget.dart';
import 'package:comunic/ui/widgets/network_image_widget.dart';
import 'package:comunic/utils/account_utils.dart';
import 'package:comunic/utils/files_utils.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/material.dart';

import '../../../models/api_request.dart';
import '../../../utils/ui_utils.dart';

/// Emojies account settings
///
/// @author Pierre Hubert

class CustomEmojisAccountSettings extends StatefulWidget {
  @override
  _CustomEmojisAccountSettingsState createState() =>
      _CustomEmojisAccountSettingsState();
}

class _CustomEmojisAccountSettingsState
    extends State<CustomEmojisAccountSettings> {
  User _user;

  final _key = GlobalKey<AsyncScreenWidgetState>();

  Future<void> _reload() async {
    _user = await UsersHelper().getSingleWithThrow(
      userID(),
      forceDownload: true,
    );
  }

  @override
  Widget build(BuildContext context) {
    return AsyncScreenWidget(
      key: _key,
      onReload: _reload,
      onBuild: _buildSettings,
      errorMessage: tr("Could not refresh user information!"),
      showOldDataWhileUpdating: true,
    );
  }

  Widget _buildSettings() {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Stack(
        children: [_buildList(), _buildAddButton()],
      ),
    );
  }

  Widget _buildList() {
    return ListView(
        children: _user.customEmojies
            .map((u) => ListTile(
                  leading: NetworkImageWidget(url: u.url, width: 50),
                  title: Text(u.shortcut),
                  trailing: IconButton(
                      icon: Icon(Icons.delete),
                      onPressed: () => _deleteEmoji(u)),
                ))
            .toList());
  }

  Widget _buildAddButton() {
    return Positioned(
      child: FloatingActionButton(
        onPressed: _addEmoji,
        child: Icon(Icons.add),
      ),
      right: 20,
      bottom: 20,
    );
  }

  /// Add a custom emoji
  void _addEmoji() async {
    try {
      final newEmoji = await showDialog<NewEmoji>(
        context: context,
        builder: (c) => _NewCustomEmojiDialog(
          currentList: _user.customEmojies,
        ),
      );

      if (newEmoji == null) return;

      await SettingsHelper.uploadNewCustomEmoji(newEmoji);
    } catch (e, stack) {
      print("Could not add a new emoji: $e\n$stack");
      showSimpleSnack(context, tr("Could not upload emoji!"));
    }

    _key.currentState.refresh();
  }

  /// Ask for confirmation before deleting permanently an emoji
  void _deleteEmoji(CustomEmoji u) async {
    try {
      if (!await showConfirmDialog(
          context: context,
          message: tr("Do you really want to delete this custom emoji ?")))
        return;

      await SettingsHelper.deleteCustomEmoji(u.id);
    } catch (e, stack) {
      print("Could not delete custom emoji! $e\n$stack");
      showSimpleSnack(context, tr("Could not delete custom emoji!"));
    }

    _key.currentState.refresh();
  }
}

/// Dialog used to upload new custom emojies
class _NewCustomEmojiDialog extends StatefulWidget {
  final CustomEmojiesList currentList;

  const _NewCustomEmojiDialog({
    Key key,
    @required this.currentList,
  })  : assert(currentList != null),
        super(key: key);

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

class _NewCustomEmojiDialogState extends State<_NewCustomEmojiDialog> {
  final _controller = TextEditingController();
  BytesFile _file;

  bool get _hasImage => _file != null;

  String get _shortcut => _controller.text;

  bool get _shortcutValid =>
      _shortcut.isNotEmpty &&
      validateShortcut(_shortcut) &&
      !widget.currentList.hasShortcut(_shortcut);

  bool get _valid => _hasImage && _shortcutValid;

  NewEmoji get _emoji => NewEmoji(shortcut: _shortcut, image: _file);

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Text(tr("Add new emoji")),
      content: ConstrainedBox(
        constraints:
            BoxConstraints(maxHeight: MediaQuery.of(context).size.height - 50),
        child: SingleChildScrollView(
          child: _buildBody(),
        ),
      ),
      actions: <Widget>[
        MaterialButton(
          onPressed: () => Navigator.of(context).pop(),
          child: Text(tr("Cancel").toUpperCase()),
        ),
        MaterialButton(
          onPressed: _valid ? () => Navigator.of(context).pop(_emoji) : null,
          child: Text(tr("Add").toUpperCase()),
        ),
      ],
    );
  }

  Widget _buildBody() {
    return Column(
      children: <Widget>[
        TextField(
          controller: _controller,
          onChanged: (s) => setState(() {}),
          decoration: InputDecoration(
            alignLabelWithHint: true,
            labelText: tr("Shortcut"),
            hintText: tr(":yourShortcut:"),
            errorText: _shortcut.isNotEmpty && !_shortcutValid
                ? tr("Invalid shortcut!")
                : null,
          ),
        ),
        MaterialButton(
          onPressed: _pickImage,
          child: Text(_hasImage ? tr("Replace image") : tr("Add image")),
        )
      ],
    );
  }

  void _pickImage() async {
    try {
      final image = await pickImage(context);

      if (image == null) return;

      setState(() {
        _file = image;
      });
    } catch (e, stack) {
      print("Could not pick an image! $e\n$stack");
      snack(context, tr("Failed to pick an image!"));
    }
  }
}