import 'package:comunic/helpers/account_helper.dart';
import 'package:comunic/helpers/events_helper.dart';
import 'package:comunic/helpers/preferences_helper.dart';
import 'package:comunic/helpers/server_config_helper.dart';
import 'package:comunic/helpers/version_helper.dart';
import 'package:comunic/helpers/websocket_helper.dart';
import 'package:comunic/models/config.dart';
import 'package:comunic/ui/dialogs/deprecation_dialog.dart';
import 'package:comunic/ui/routes/main_route/main_route.dart';
import 'package:comunic/ui/routes/main_route/smartphone_route.dart';
import 'package:comunic/ui/routes/main_route/tablet_route.dart';
import 'package:comunic/ui/routes/tour_route.dart';
import 'package:comunic/ui/routes/welcome_route.dart';
import 'package:comunic/ui/widgets/login_routes_theme.dart';
import 'package:comunic/ui/widgets/safe_state.dart';
import 'package:comunic/utils/flutter_utils.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/ui_utils.dart';
import 'package:flutter/material.dart';

/// Comunic account initialization widget
///
/// Application screens should only appears as children of this widget
///
/// This widget ensures that the application is correctly initialized before
/// starting it
///
/// @author Pierre Hubert

class InitializeWidget extends StatefulWidget {
  @override
  _InitializeWidgetState createState() => _InitializeWidgetState();
}

class _InitializeWidgetState extends SafeState<InitializeWidget> {
  bool _error = false;

  @override
  void initState() {
    _tryConnect();

    super.initState();

    // Check if login token are considered as invalid
    super.listen<InvalidLoginTokensEvent>((ev) => _openLoginPage());

    // Listen to WebSocket close event
    super.listen<WSClosedEvent>((e) {
      _popToMainRoute();
      _tryConnect();
    });
  }

  @override
  void dispose() {
    super.dispose();
    WebSocketHelper.close();
  }

  /// Open login page
  _openLoginPage() {
    Navigator.of(context)
        .pushReplacement(MaterialPageRoute(builder: (c) => WelcomeRoute()));
  }

  /// Try to connect to server
  void _tryConnect() async {
    try {
      await ServerConfigurationHelper.ensureLoaded();

      if (!isWeb &&
          ServerConfigurationHelper.config.minSupportedMobileVersion >
              VersionHelper.version) await showDeprecationDialog(context);

      if (!AccountHelper.isUserIDLoaded) {
        _popToMainRoute();
        _openLoginPage();
        return;
      }

      setState(() {
        _error = false;
      });

      final prefs = await PreferencesHelper.getInstance();
      if (!prefs.getBool(PreferencesKeyList.IS_TOUR_SEEN)) {
        await WebSocketHelper.connect();
        await showTour(context);
      }

      print("Attempting WebSocket connection...");

      if (config().additionalLoading != null)
        await config().additionalLoading();

      await WebSocketHelper.connect();

      setState(() {});
    } catch (e, stack) {
      print("Could not connect to server! $e");
      print(stack);

      _popToMainRoute();

      setState(() {
        _error = true;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    if (_error || !WebSocketHelper.isConnected()) return _buildNonReadyWidget();

    if (config().mainRouteBuilder != null)
      return config().mainRouteBuilder(context, mainControllerKey);

    return isTablet(context)
        ? TabletRoute(key: mainControllerKey)
        : SmartphoneMainRoute(key: mainControllerKey);
  }

  /// Build loading widget
  Widget _buildNonReadyWidget() {
    return LoginRoutesTheme(
      child: Scaffold(
        backgroundColor: config().splashBackgroundColor,
        body: Center(
          child: Material(
            color: Colors.transparent,
            textStyle: TextStyle(color: Colors.white),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                Spacer(
                  flex: 4,
                ),
                Text(
                  config().appName,
                  style: TextStyle(fontSize: 50),
                ),
                Spacer(
                  flex: 2,
                ),
                _error ? _buildErrorWidget() : _buildConnectingWidget(),
                Spacer(
                  flex: 2,
                ),
                !isWeb
                    ? Text(tr("Version %version% - Build %build%", args: {
                        "version": VersionHelper.info.version.toString(),
                        "build": VersionHelper.info.buildNumber.toString()
                      }))
                    : Container(),
                Spacer(flex: 1),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildConnectingWidget() {
    return CircularProgressIndicator();
  }

  Widget _buildErrorWidget() {
    return Column(
      children: <Widget>[
        Icon(Icons.error, color: Colors.white),
        SizedBox(height: 30),
        Text(tr("Could not connect to server!")),
        SizedBox(
          height: 30,
        ),
        ElevatedButton(
          onPressed: () => _tryConnect(),
          child: Text(tr("Try again")),
        ),
      ],
    );
  }

  void _popToMainRoute() {
    // Pop until we reach main route
    Navigator.of(context).popUntil((settings) =>
        ModalRoute.of(context).isCurrent || !ModalRoute.of(context).isActive);
  }
}