import 'package:comunic/helpers/conversations_helper.dart';
import 'package:comunic/helpers/events_helper.dart';
import 'package:comunic/models/conversation.dart';
import 'package:comunic/ui/dialogs/screen_dialog.dart';
import 'package:comunic/ui/routes/main_route/main_route.dart';
import 'package:comunic/ui/routes/update_conversation_route.dart';
import 'package:comunic/ui/screens/conversation_members_screen.dart';
import 'package:comunic/ui/screens/conversation_screen.dart';
import 'package:comunic/ui/widgets/safe_state.dart';
import 'package:comunic/ui/widgets/tablet_mode/conversations/conversation_window_container.dart';
import 'package:comunic/utils/account_utils.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/material.dart';

/// Single conversation window
///
/// @author Pierre Hubert

enum _Actions { OPEN_FULL_SCREEN, OPEN_MEMBERS, OPEN_SETTINGS }

class ConversationWindow extends StatefulWidget {
  final int convID;
  final Function() onClose;

  const ConversationWindow({
    Key key,
    @required this.convID,
    @required this.onClose,
  })  : assert(convID != null),
        assert(onClose != null),
        super(key: key);

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

class _ConversationWindowState extends SafeState<ConversationWindow> {
  Conversation _conversation;
  String _convTitle;
  bool _error = false;
  bool _collapsed = false;
  bool _hasNewMessages = false;

  int get _convID => widget.convID;

  final _convKey = UniqueKey();

  void _setError(bool e) => setState(() => _error = e);

  void _toggleVisibility() => setState(() {
        _collapsed = !_collapsed;
        if (!_collapsed) _hasNewMessages = false;
      });

  Future<void> _refresh() async {
    try {
      _setError(false);

      final conversation =
          await ConversationsHelper().getSingle(_convID, force: true);
      assert(conversation != null);
      final name =
          await ConversationsHelper.getConversationNameAsync(conversation);
      assert(name != null);

      setState(() {
        _conversation = conversation;
        _convTitle = name;
      });
    } catch (e, s) {
      _setError(true);
      print("Could not refresh the list of conversations! $e\n$s");
      showSimpleSnack(context, tr("Could not load conversation information!"));
    }
  }

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

    listen<NewConversationMessageEvent>((e) {
      if (e.msg.convID == _convID &&
          _collapsed &&
          e.msg.userID != userID()) setState(() => _hasNewMessages = true);
    });
  }

  @override
  Widget build(BuildContext context) {
    // In case of error
    if (_error)
      return ConversationWindowContainer(
        icon: Icon(Icons.error),
        title: Text(tr("Error")),
        onClose: widget.onClose,
        onToggleCollapse: _toggleVisibility,
        isCollapsed: _collapsed,
        body: buildErrorCard(tr("Could not load conversation information!"),
            actions: [
              FlatButton(
                textColor: Colors.white,
                onPressed: _refresh,
                child: Text(tr("Try again").toUpperCase()),
              )
            ]),
      );

    // If it is still loading
    if (_conversation == null)
      return ConversationWindowContainer(
        icon: Icon(Icons.message),
        title: Text(tr("Loading...")),
        onClose: widget.onClose,
        onToggleCollapse: _toggleVisibility,
        isCollapsed: _collapsed,
        body: buildCenteredProgressBar(),
      );

    return ConversationWindowContainer(
      icon: _hasNewMessages ? Icon(Icons.trip_origin) : null,
      appBarBgColor: _hasNewMessages ? Colors.green : null,
      title: Text(_convTitle),
      onClose: widget.onClose,
      onToggleCollapse: _toggleVisibility,
      isCollapsed: _collapsed,
      action: (_conversation.callCapabilities != CallCapabilities.NONE
          ? [IconButton(icon: Icon(Icons.call), onPressed: _startCall)]
          : [])
        ..addAll(<Widget>[
          PopupMenuButton<_Actions>(
            itemBuilder: (c) => [
              // Show in full screen
              PopupMenuItem(
                child: Text(tr("Open in full screen")),
                value: _Actions.OPEN_FULL_SCREEN,
              ),

              // Show the list of members
              PopupMenuItem(
                child: Text(tr("Members")),
                value: _Actions.OPEN_MEMBERS,
              ),

              // Show conversation settings
              PopupMenuItem(
                child: Text(tr("Settings")),
                value: _Actions.OPEN_SETTINGS,
              )
            ],
            onSelected: _menuCallback,
          ),
        ]),
      body: ConversationScreen(
        key: _convKey,
        conversationID: _convID,
      ),
    );
  }

  void _menuCallback(_Actions value) {
    switch (value) {
      case _Actions.OPEN_FULL_SCREEN:
        _openFullScreen();
        break;

      case _Actions.OPEN_MEMBERS:
        _openMembersList();
        break;

      case _Actions.OPEN_SETTINGS:
        _openConversationSettings();
        break;
    }
  }

  void _openFullScreen() {
    MainController.of(context).openConversation(_convID, fullScreen: true);
    widget.onClose();
  }

  void _openMembersList() {
    showScreenDialog(context, ConversationMembersScreen(convID: _convID));
  }

  void _openConversationSettings() async {
    await showScreenDialog(
        context, UpdateConversationRoute(conversationID: _convID));
    _refresh();
  }

  void _startCall() => MainController.of(context).startCall(_convID);
}