import 'package:comunic/helpers/account_helper.dart';
import 'package:comunic/ui/routes/account_settings/account_settings_route.dart';
import 'package:comunic/ui/routes/app_settings_route.dart';
import 'package:comunic/ui/routes/conversation_route.dart';
import 'package:comunic/ui/screens/conversations_list_screen.dart';
import 'package:comunic/ui/screens/friends_list_screen.dart';
import 'package:comunic/ui/screens/group_screen.dart';
import 'package:comunic/ui/screens/groups_list_screen.dart';
import 'package:comunic/ui/screens/newest_posts.dart';
import 'package:comunic/ui/screens/notifications_screen.dart';
import 'package:comunic/ui/screens/other_friends_lists_screen.dart';
import 'package:comunic/ui/screens/search_screen.dart';
import 'package:comunic/ui/screens/user_access_denied_screen.dart';
import 'package:comunic/ui/screens/user_page_screen.dart';
import 'package:comunic/ui/widgets/navbar_widget.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';

import 'login_route.dart';

/// Main route of the application
///
/// @author Pierre HUBERT

class MainRoute extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _MainRouteState();
}

class CurrPage {
  final BarCallbackActions action;
  final Map<String, dynamic> args;
  final bool hideNavBar;

  const CurrPage(
    this.action, {
    this.args,
    this.hideNavBar = false,
  })  : assert(action != null),
        assert(hideNavBar != null);

  @override
  String toString() =>
      "CurrPage {\n\taction: " +
      this.action.toString() +
      "\n\targs: " +
      this.args.toString() +
      "\n}";
}

/// Public interface of home controller
abstract class MainController extends State<MainRoute> {
  /// Get current instance of Home controller
  static MainController of(BuildContext context) =>
      context.findAncestorStateOfType<MainController>();

  /// Open user page
  void openUserPage(int userID);

  void openUserAccessDeniedPage(int userID);

  /// Open a specific group page specified by its [groupID]
  void openGroup(int groupID);

  /// Display the list of friends of a user
  void openUserFriendsList(int userID);

  /// Pop current page. Last page can not be popped
  void popPage();

  /// Push a new widget
  void push(Widget w, {bool hideNavBar});

  /// Open a conversation
  void openConversation(int convID);
}

/// Private implementation of HomeController
class _MainRouteState extends MainController {
  CurrPage get _currTab => history.last;
  List<CurrPage> history = List();

  /// Change currently visible tab
  void _pushPage(CurrPage newPage) {
    setState(() {
      history.add(newPage);
    });
  }

  /// Pop the page
  void popPage() {
    if (history.length > 1) history.removeLast();
    setState(() {});
  }

  /// Allows to go to previous tab
  Future<bool> _willPop() async {
    if (history.length == 1) return true;

    popPage();
    return false;
  }

  /// Handles a new tab being tapped
  void _onTap(BarCallbackActions action) {
    /// Check more quick actions
    switch (action) {

      /// Open current user page
      case BarCallbackActions.OPEN_MY_PAGE:
        _openCurrentUserPage();
        break;

      /// Open app settings page
      case BarCallbackActions.OPEN_APP_SETTINGS:
        _openAppSettings();
        break;

      case BarCallbackActions.OPEN_ACCOUNT_SETTINGS:
        _openAccountsSettings();
        break;

      /// Show about dialog
      case BarCallbackActions.OPEN_ABOUT_DIALOG:
        showAboutAppDialog(context);
        break;

      /// Logout user
      case BarCallbackActions.ACTION_LOGOUT:
        _logoutRequested();
        break;

      default:
        _pushPage(CurrPage(action));
    }
  }

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

    // Default page: conversations list
    _pushPage(CurrPage(BarCallbackActions.OPEN_NOTIFICATIONS));
  }

  /// Build the body of the application
  Widget _buildBody(BuildContext context) {
    switch (_currTab.action) {
      case BarCallbackActions.OPEN_CUSTOM_WIDGET:
        return _currTab.args["widget"];

      case BarCallbackActions.OPEN_NOTIFICATIONS:
        return NotificationsScreen();

      case BarCallbackActions.OPEN_CONVERSATIONS:
        return ConversationsListScreen();

      case BarCallbackActions.OPEN_NEWEST_POSTS:
        return NewestPostsScreen();

      case BarCallbackActions.OPEN_FRIENDS:
        return FriendsListScreen();

      case BarCallbackActions.OPEN_USER_PAGE:
        return UserPageScreen(userID: _currTab.args["userID"]);

      case BarCallbackActions.OPEN_USER_ACCESS_DENIED_PAGE:
        return UserAccessDeniedScreen(userID: _currTab.args["userID"]);

      case BarCallbackActions.OPEN_SEARCH_PAGE:
        return SearchScreen();

      case BarCallbackActions.OPEN_GROUPS:
        return GroupsListScreen();

      case BarCallbackActions.OPEN_GROUP_PAGE:
        return GroupPageScreen(groupID: _currTab.args["groupID"]);

      case BarCallbackActions.OPEN_USER_FRIENDS_LIST:
        return OtherUserFriendsListScreen(
          userID: _currTab.args["userID"],
        );

      case BarCallbackActions.OPEN_CONVERSATION:
        return ConversationRoute(
          conversationID: _currTab.args["convID"],
        );

      default:
        throw "Invalid tab : " + _currTab.toString();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.blueAccent,
      child: SafeArea(
        // Avoid OS areas
        child: WillPopScope(
          onWillPop: _willPop,
          child: Scaffold(
            appBar: _currTab.hideNavBar
                ? null
                : ComunicAppBar(
                    onTap: _onTap,
                    selectedAction: _currTab.action,
                  ),
            body: SafeArea(
              child: _buildBody(context),
            ),
          ),
        ),
      ),
    );
  }

  /// Open current user page
  Future<void> _openCurrentUserPage() async {
    this.openUserPage(userID());
  }

  void _openAppSettings() {
    Navigator.of(context)
        .push(MaterialPageRoute(builder: (c) => AppSettingsRoute()));
  }

  void _openAccountsSettings() {
    Navigator.of(context)
        .push(MaterialPageRoute(builder: (c) => AccountSettingsRoute()));
  }

  /// Handle logout requests from user
  Future<void> _logoutRequested() async {
    if (!await showConfirmDialog(
        context: context,
        message: tr("Do you really want to sign out from the application ?"),
        title: tr("Sign out"))) return;

    await AccountHelper().signOut();

    Navigator.pushReplacement(context, MaterialPageRoute(builder: (c) {
      return LoginRoute();
    }));
  }

  @override
  void openGroup(int groupID) {
    _pushPage(CurrPage(BarCallbackActions.OPEN_GROUP_PAGE,
        args: {"groupID": groupID}));
  }

  @override
  void openUserPage(int userID) {
    _pushPage(
        CurrPage(BarCallbackActions.OPEN_USER_PAGE, args: {"userID": userID}));
  }

  @override
  void openUserAccessDeniedPage(int userID) {
    _pushPage(CurrPage(BarCallbackActions.OPEN_USER_ACCESS_DENIED_PAGE,
        args: {"userID": userID}));
  }

  @override
  void openUserFriendsList(int userID) {
    _pushPage(CurrPage(BarCallbackActions.OPEN_USER_FRIENDS_LIST,
        args: {"userID": userID}));
  }

  @override
  void push(Widget w, {bool hideNavBar = false}) {
    _pushPage(CurrPage(
      BarCallbackActions.OPEN_CUSTOM_WIDGET,
      args: {"widget": w},
      hideNavBar: hideNavBar,
    ));
  }

  @override
  void openConversation(int convID) {
    _pushPage(CurrPage(
      BarCallbackActions.OPEN_CONVERSATION,
      args: {"convID": convID},
      hideNavBar: true,
    ));
  }
}