import 'package:comunic/helpers/conversations_helper.dart';
import 'package:comunic/helpers/friends_helper.dart';
import 'package:comunic/helpers/groups_helper.dart';
import 'package:comunic/helpers/users_helper.dart';
import 'package:comunic/helpers/webapp_helper.dart';
import 'package:comunic/lists/groups_list.dart';
import 'package:comunic/lists/memberships_list.dart';
import 'package:comunic/lists/users_list.dart';
import 'package:comunic/models/friend.dart';
import 'package:comunic/models/membership.dart';
import 'package:comunic/ui/routes/main_route/main_route.dart';
import 'package:comunic/ui/routes/main_route/page_info.dart';
import 'package:comunic/ui/widgets/account_image_widget.dart';
import 'package:comunic/ui/widgets/conversation_image_widget.dart';
import 'package:comunic/ui/widgets/group_icon_widget.dart';
import 'package:comunic/ui/widgets/group_membership_widget.dart';
import 'package:comunic/ui/widgets/safe_state.dart';
import 'package:comunic/utils/date_utils.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/material.dart';

/// Memberships panel
///
/// @author Pierre Hubert

class MembershipsPanel extends StatefulWidget {
  final PageInfo currentPage;

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

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

const _MembershipIconsWidth = 30.0;

class _MembershipsPanelState extends SafeState<MembershipsPanel> {
  final _refreshKey = GlobalKey<RefreshIndicatorState>();
  MembershipList _membershipList;
  UsersList _usersList;
  GroupsList _groupsList;

  Future<void> _refresh() async {
    try {
      final memberships = await WebAppHelper.getMemberships();
      final users = await UsersHelper().getListWithThrow(memberships.usersId);
      final groups = await GroupsHelper().getListOrThrow(memberships.groupsId);

      setState(() {
        _membershipList = memberships;
        _usersList = users;
        _groupsList = groups;
      });
    } catch (e, s) {
      print("Could not load the list of memberships! $e\n$s");
    }
  }

  @override
  void initState() {
    super.initState();
    setInterval(20, (t) => _refresh());
    _refresh();
  }

  @override
  Widget build(BuildContext context) {
    if (_membershipList == null) return buildCenteredProgressBar();

    return Material(
      color: Colors.transparent,
      child: RefreshIndicator(
          key: _refreshKey,
          child: _buildMembershipsList(),
          onRefresh: _refresh),
    );
  }

  Widget _buildMembershipsList() {
    return ListTileTheme(
      iconColor: IconTheme.of(context).color,
      child: ListView.builder(
        itemBuilder: _buildMembershipTile,
        itemCount: _membershipList.length,
      ),
    );
  }

  Widget _buildMembershipTile(BuildContext context, int index) {
    final membership = _membershipList[index];

    switch (membership.type) {
      case MembershipType.FRIEND:
        return _buildFriendMembership(membership);

      case MembershipType.GROUP:
        return _buildGroupMembership(membership);

      case MembershipType.CONVERSATION:
        return _buildConversationMembership(membership);
    }

    throw Exception("Unreachable statement!");
  }

  // TODO : add private messages icon support
  Widget _buildFriendMembership(Membership membership) {
    final user = _usersList.getUser(membership.friend.id);
    final connected = membership.friend.isConnected;

    Widget subtitle;

    if (!membership.friend.accepted) {
      subtitle = RichText(
          text: TextSpan(children: [
        WidgetSpan(
            child: _RespondFriendshipRequestButton(
          friend: membership.friend,
          accept: true,
          text: tr("Accept"),
          color: Colors.green,
          onTap: _respondFriendshipRequest,
        )),
        TextSpan(text: "   "),
        WidgetSpan(
            child: _RespondFriendshipRequestButton(
          friend: membership.friend,
          accept: false,
          text: tr("Reject"),
          color: Colors.red,
          onTap: _respondFriendshipRequest,
        )),
      ]));
    } else
      subtitle = Text(
        connected ? tr("Online") : diffTimeFromNowToStr(membership.lastActive),
        style: TextStyle(color: connected ? Colors.green : null),
      );

    return Container(
      color: widget.currentPage.type == PageType.USER_PAGE &&
              widget.currentPage.id == user.id
          ? Colors.grey.shade800
          : null,
      child: ListTile(
        leading: AccountImageWidget(user: user, width: _MembershipIconsWidth),
        title: Text(user.displayName),
        subtitle: subtitle,
        onTap: () => MainController.of(context).openUserPage(user.id),
      ),
    );
  }

  Widget _buildGroupMembership(Membership membership) {
    final group = _groupsList.getGroup(membership.groupID);

    Widget subtitle;

    if (!group.isAtLeastMember) {
      subtitle = GroupMembershipWidget(
        group: group,
        onUpdated: () => _refreshKey.currentState.show(),
        onError: _onGroupMembershipUpdateError,
      );
    } else {
      subtitle = Text(diffTimeFromNowToStr(membership.lastActive));
    }

    return Container(
      color: widget.currentPage.type == PageType.GROUP_PAGE &&
              widget.currentPage.id == group.id
          ? Colors.grey.shade800
          : null,
      child: ListTile(
        leading: GroupIcon(
          group: group,
          width: _MembershipIconsWidth,
        ),
        title: Text(group.displayName),
        subtitle: subtitle,
        onTap: () => MainController.of(context).openGroup(group.id),
      ),
    );
  }

  Widget _buildConversationMembership(Membership membership) {
    final conversation = membership.conversation;

    Color color;
    if (conversation.isHavingCall)
      color = Color(0xFF815d1d);
    else if (widget.currentPage.type == PageType.CONVERSATION_PAGE &&
        widget.currentPage.id == conversation.id)
      color = Colors.grey.shade800;
    else if (!conversation.sawLastMessage) color = Color(0xFF1c443a);

    return Container(
      color: color,
      child: ListTile(
        dense: true,
        leading: ConversationImageWidget(
          conversation: conversation,
          users: _usersList,
        ),
        title: Row(
          children: [
            Icon(
              Icons.message,
              size: 12,
            ),
            SizedBox(width: 5),
            Text(ConversationsHelper.getConversationName(
                conversation, _usersList)),
          ],
        ),
        subtitle: Text(diffTimeFromNowToStr(membership.lastActive) +
            (conversation.isHavingCall ? "\n" + tr("Ongoing call") : "")),
        onTap: () => MainController.of(context)
            .openConversation(conversation.id, fullScreen: true),
        trailing: conversation.isHavingCall
            ? FloatingActionButton(
                heroTag: null,
                child: Icon(Icons.call),
                onPressed: () =>
                    MainController.of(context).startCall(conversation.id),
              )
            : null,
      ),
    );
  }

  /// Respond to a friendship request
  Future<void> _respondFriendshipRequest(Friend f, bool accept) async {
    try {
      if (!accept &&
          !await showConfirmDialog(
              context: context,
              message:
                  tr("Do you really want to reject this friendship request?")))
        return;

      await FriendsHelper().respondRequest(f.id, accept);

      setState(() {
        if (accept)
          f.accepted = true;
        else
          _membershipList.removeFriend(f.id);
      });
      _refreshKey.currentState.show();
    } catch (e, s) {
      print("Could not respond to friendship request! $e\n$s");
      showSimpleSnack(context, tr("Could not respond to friendship request!"));
    }
  }

  /// Handles the case of failure in group membership update
  void _onGroupMembershipUpdateError() {
    showSimpleSnack(context, tr("Could not update group membership!"));
    _refreshKey.currentState.show();
  }
}

class _RespondFriendshipRequestButton extends StatelessWidget {
  final Friend friend;
  final bool accept;
  final String text;
  final Color color;
  final void Function(Friend, bool) onTap;

  const _RespondFriendshipRequestButton({
    Key key,
    @required this.friend,
    @required this.accept,
    @required this.text,
    @required this.color,
    @required this.onTap,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () => onTap(friend, accept),
      child: Text(text, style: TextStyle(color: color)),
    );
  }
}