import 'package:comunic/helpers/serialization/user_list_serialization_helper.dart';
import 'package:comunic/helpers/settings_helper.dart';
import 'package:comunic/models/account_image_settings.dart';
import 'package:comunic/ui/dialogs/multi_choices_dialog.dart';
import 'package:comunic/ui/widgets/async_screen_widget.dart';
import 'package:comunic/ui/widgets/network_image_widget.dart';
import 'package:comunic/ui/widgets/settings/header_spacer_section.dart';
import 'package:comunic/ui/widgets/settings/multi_choices_settings_tile.dart';
import 'package:comunic/utils/account_utils.dart';
import 'package:comunic/utils/files_utils.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/material.dart';
import 'package:identicon/identicon.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:random_string/random_string.dart';
import 'package:settings_ui/settings_ui.dart';

import '../../../utils/log_utils.dart';
import '../../../utils/ui_utils.dart';

/// Account image settings section
///
/// @author Pierre Hubert

class AccountImageSettingsScreen extends StatefulWidget {
  @override
  _AccountImageSettingsScreenState createState() =>
      _AccountImageSettingsScreenState();
}

class _AccountImageSettingsScreenState
    extends State<AccountImageSettingsScreen> {
  AccountImageSettings _settings;

  final _key = GlobalKey<AsyncScreenWidgetState>();

  @override
  void dispose() {
    // Remove current user information to force refresh of account image
    UsersListSerialisationHelper().removeUserByID(userID());

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AsyncScreenWidget(
      key: _key,
      onReload: () async =>
          _settings = await SettingsHelper.getAccountImageSettings(),
      onBuild: () => _buildLayout(),
      errorMessage: tr("Could not get account image settings!"),
    );
  }

  Widget _buildLayout() {
    return SettingsList(
      sections: [
        HeadSpacerSection(),
        SettingsSection(
          title: tr("General"),
          tiles: _settings.hasImage
              ? _buildHasAccountImageTiles()
              : _buildNoAccountImageTiles(),
        )
      ],
    );
  }

  /// When user has no account image yet
  List<SettingsTile> _buildNoAccountImageTiles() {
    return [
      SettingsTile(
        title: tr("No account image yet..."),
        leading: NetworkImageWidget(
          url: _settings.imageURL,
          width: 40,
        ),
      ),

      // Upload new account image
      SettingsTile(
        title: tr("Upload an account image"),
        onPressed: (_) => _uploadAccountImage(),
      ),

      // Generate a random account image
      SettingsTile(
        title: tr("Generate a random account image"),
        onPressed: (_) => _generateRandomAccountImage(),
      ),
    ];
  }

  List<MultiChoiceEntry<AccountImageVisibilityLevels>> get _visibilityLevels =>
      [
        MultiChoiceEntry(
          id: AccountImageVisibilityLevels.EVERYONE,
          title: tr("Everyone"),
          subtitle: tr(
              "Your account image is visible by everyone, including users external to Comunic."),
        ),
        MultiChoiceEntry(
          id: AccountImageVisibilityLevels.COMUNIC_USERS,
          title: tr("Connected users"),
          subtitle: tr(
              "Your account image is visible only to connected Comunic users."),
        ),
        MultiChoiceEntry(
          id: AccountImageVisibilityLevels.FRIENDS_ONLY,
          title: tr("My friends"),
          subtitle: tr("Your account image is visible only by your friends."),
        ),
      ];

  /// When the user has an account image
  List<SettingsTile> _buildHasAccountImageTiles() {
    return [
      // Current account image (if any)
      SettingsTile(
        title: tr("Current account image"),
        leading: NetworkImageWidget(
          url: _settings.imageURL,
          width: 40,
        ),
      ),

      // Upload new account image
      SettingsTile(
        title: tr("Upload new account image"),
        onPressed: (_) => _uploadAccountImage(),
      ),

      // Generate a random account image
      SettingsTile(
        title: tr("Generate a random account image"),
        onPressed: (_) => _generateRandomAccountImage(),
      ),

      // Change account image visibility
      MultiChoicesSettingsTile(
          title: tr("Account image visibility"),
          choices: _visibilityLevels,
          currentValue: _settings.visibility,
          onChanged: (newLevel) async {
            if (!await SettingsHelper.setAccountImageVisibilityLevel(newLevel))
              showSimpleSnack(context,
                  tr("Could not update account image visibility level!"));
            _key.currentState.refresh();
          }),

      // Delete account image
      SettingsTile(
        title: tr("Delete account image"),
        onPressed: (_) => _deleteAccountImage(),
      ),
    ];
  }

  /// Upload a new account image
  void _uploadAccountImage() async {
    await uploadNewAccountImage(context);
    _key.currentState.refresh();
  }

  /// Generate a random account image
  void _generateRandomAccountImage() async {
    // Generate emoticon
    final bytes = Identicon().generate(randomString(10));

    if (!await SettingsHelper.uploadAccountImageFromMemory(bytes)) {
      showSimpleSnack(
          context, tr("Could not upload your generated account image!"));
      return;
    }

    _key.currentState.refresh();
  }

  /// Delete user account image
  void _deleteAccountImage() async {
    if (!await showConfirmDialog(
        context: context,
        message: tr("Do you really want to delete your account image ?")))
      return;

    if (!await SettingsHelper.deleteAccountImage()) {
      showSimpleSnack(context, tr("Could not delete user account image!"));
      return;
    }

    _key.currentState.refresh();
  }
}

Future<void> uploadNewAccountImage(BuildContext context) async {
  try {
    final image = await pickImage(context,
        aspectRatio: CropAspectRatio(ratioX: 5, ratioY: 5));

    if (image == null) return;

    await SettingsHelper.uploadAccountImage(image);
  } catch (e, s) {
    logError(e, s);
    snack(context, tr("Failed to upload new account image!"));
  }
}