import 'package:comunic/helpers/events_helper.dart';
import 'package:comunic/helpers/notifications_helper.dart';
import 'package:comunic/models/count_unread_notifications.dart';
import 'package:comunic/ui/widgets/safe_state.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/material.dart';

/// Navigation bar widget
///
/// @author Pierre HUBERT

typedef OnSelectMenuAction = void Function(BarCallbackActions);

/// Callback actions
enum BarCallbackActions {
  OPEN_CUSTOM_WIDGET,
  OPEN_NOTIFICATIONS,
  OPEN_CONVERSATIONS,
  OPEN_NEWEST_POSTS,
  OPEN_FRIENDS,
  OPEN_MY_PAGE,
  OPEN_SEARCH_PAGE,
  OPEN_GROUPS,
  OPEN_GROUP_PAGE,
  OPEN_USER_PAGE,
  OPEN_USER_ACCESS_DENIED_PAGE,
  OPEN_ACCOUNT_SETTINGS,
  OPEN_APP_SETTINGS,
  OPEN_USER_FRIENDS_LIST,
  OPEN_CONVERSATION,
  NONE,
  ACTION_LOGOUT
}

Color _primaryColor() => darkTheme() ? Colors.black : Colors.blue;

Color _secondaryColor() => darkTheme() ? darkAccentColor : Colors.white;

/// Menu item information
class _MenuItem {
  final String label;
  final Widget icon;
  final BarCallbackActions action;
  final bool isMenu;

  const _MenuItem({
    @required this.label,
    @required this.icon,
    @required this.action,
    this.isMenu = false,
  })  : assert(label != null),
        assert(icon != null || isMenu),
        assert(action != null),
        assert(isMenu != null);
}

/// Item of action menu
class _ActionMenuItem {
  final String label;
  final BarCallbackActions action;

  const _ActionMenuItem({@required this.label, @required this.action})
      : assert(label != null),
        assert(action != null);
}

/// List of menu items to show
final _menuItems = <_MenuItem>[
  _MenuItem(
      label: tr("Notifications"),
      icon: Icon(Icons.notifications),
      action: BarCallbackActions.OPEN_NOTIFICATIONS),
  _MenuItem(
      label: tr("Conversations"),
      icon: Icon(Icons.comment),
      action: BarCallbackActions.OPEN_CONVERSATIONS),
  _MenuItem(
      label: tr("Newest"),
      icon: Icon(Icons.refresh),
      action: BarCallbackActions.OPEN_NEWEST_POSTS),
  _MenuItem(
      label: tr("Friends"),
      icon: Icon(Icons.group),
      action: BarCallbackActions.OPEN_FRIENDS),
  _MenuItem(
      label: tr("Menu"),
      icon: Icon(Icons.more_vert),
      isMenu: true,
      action: BarCallbackActions.NONE)
];

/// List of menu actions items
final _menuActionsItem = <_ActionMenuItem>[
  _ActionMenuItem(
      label: tr("My Page"), action: BarCallbackActions.OPEN_MY_PAGE),
  _ActionMenuItem(label: tr("Groups"), action: BarCallbackActions.OPEN_GROUPS),
  _ActionMenuItem(
      label: tr("Search"), action: BarCallbackActions.OPEN_SEARCH_PAGE),
  _ActionMenuItem(
      label: tr("Account settings"),
      action: BarCallbackActions.OPEN_ACCOUNT_SETTINGS),
  _ActionMenuItem(
      label: tr("App settings"), action: BarCallbackActions.OPEN_APP_SETTINGS),
  _ActionMenuItem(
      label: tr("Sign out"), action: BarCallbackActions.ACTION_LOGOUT),
];

/// Public widget
class ComunicMobileAppBar extends StatefulWidget implements PreferredSizeWidget {
  final OnSelectMenuAction onTap;
  final BarCallbackActions selectedAction;

  const ComunicMobileAppBar(
      {Key key, @required this.onTap, @required this.selectedAction})
      : assert(onTap != null),
        super(key: key);

  @override
  _ComunicMobileAppBarState createState() => _ComunicMobileAppBarState();

  @override
  Size get preferredSize => Size.fromHeight(40);
}

class _ComunicMobileAppBarState extends SafeState<ComunicMobileAppBar> {
  var _unreadNotifications =
      CountUnreadNotifications(notifications: 0, conversations: 0);

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

    // Listen to notifications number update
    this.listenChangeState<NewNumberNotifsEvent>(
        (d) => _unreadNotifications.notifications = d.newNum);
    this.listenChangeState<NewNumberUnreadConversations>(
        (d) => _unreadNotifications.conversations = d.newNum);
  }

  void _refreshCountUnread() async {
    try {
      final count = await NotificationsHelper().countUnread();

      setState(() {
        _unreadNotifications = count;
      });
    } catch (e, stack) {
      print("Could not refresh the number of unread notifications: $e");
      print(stack);
    }
  }

  /// Get the number of unread notifications for the selected notice
  int getNumberUnread(BarCallbackActions action) {
    if (_unreadNotifications == null) return 0;

    switch (action) {
      case BarCallbackActions.OPEN_NOTIFICATIONS:
        return _unreadNotifications.notifications;

      case BarCallbackActions.OPEN_CONVERSATIONS:
        return _unreadNotifications.conversations;

      default:
        return 0;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      color: darkTheme() ? Colors.black : Colors.blue,
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: List.generate(
          _menuItems.length,
          (i) => _MenuItemWidget(
            item: _menuItems[i],
            onTap: widget.onTap,
            isSelected: _menuItems[i].action == widget.selectedAction,
            newNotice: getNumberUnread(_menuItems[i].action),
          ),
        ),
      ),
    );
  }
}

/// The [Widget] part of a menu item
class _MenuItemWidget extends StatelessWidget {
  final _MenuItem item;
  final OnSelectMenuAction onTap;
  final bool isSelected;

  /// Notifications notice
  final int newNotice;

  const _MenuItemWidget({
    Key key,
    @required this.item,
    @required this.onTap,
    @required this.isSelected,
    this.newNotice = 0,
  })  : assert(item != null),
        assert(onTap != null),
        assert(isSelected != null),
        super(key: key);

  @override
  Widget build(BuildContext context) {
    assert(debugCheckHasMaterial(context));

    return Expanded(
      child: Material(
        color: isSelected ? _secondaryColor() : _primaryColor(),
        child: !item.isMenu
            ? InkWell(
                child: _buildIconContainer(),
                onTap: () => onTap(item.action),
              )
            : _buildContextMenuPopupButton(),
      ),
    );
  }

  Widget _buildIconContainer() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        Spacer(flex: 2),
        IconTheme(
          data: IconThemeData(
              color: isSelected ? _primaryColor() : _secondaryColor()),
          child: item.icon,
        ),
        newNotice > 0 ? Spacer() : Container(),
        newNotice == 0
            ? Container()
            : Material(
                color: Colors.red,
                child: Padding(
                  padding: const EdgeInsets.all(2.0),
                  child: Text(" $newNotice ",
                      style: TextStyle(color: Colors.white)),
                ),
                borderRadius: BorderRadius.all(
                  Radius.circular(50.0),
                )),
        Spacer(flex: 2),
      ],
    );
  }

  // Build context menu
  Widget _buildContextMenuPopupButton() {
    return PopupMenuButton<BarCallbackActions>(
      child: _buildIconContainer(),
      itemBuilder: (i) => _menuActionsItem
          .map((f) => PopupMenuItem(
                child: Text(f.label),
                value: f.action,
              ))
          .toList(),
      onSelected: onTap,
    );
  }
}