import 'dart:async';
import 'dart:io';
import 'package:aitrainer_app/bloc/test_set_execute/test_set_execute_bloc.dart';
import 'package:aitrainer_app/bloc/training_plan/training_plan_bloc.dart';
import 'package:aitrainer_app/bloc/tutorial/tutorial_bloc.dart';
import 'package:aitrainer_app/push_notifications.dart';
import 'package:aitrainer_app/repository/customer_repository.dart';
import 'package:aitrainer_app/repository/training_plan_repository.dart';
import 'package:aitrainer_app/repository/workout_tree_repository.dart';
import 'package:aitrainer_app/service/firebase_api.dart';
import 'package:aitrainer_app/util/session.dart';
import 'package:aitrainer_app/view/account.dart';
import 'package:aitrainer_app/view/customer_bodytype_animation.dart';
import 'package:aitrainer_app/view/customer_exercise_device.dart';
import 'package:aitrainer_app/view/customer_fitness_page.dart';
import 'package:aitrainer_app/view/customer_goal_page.dart';
import 'package:aitrainer_app/view/customer_modify_page.dart';
import 'package:aitrainer_app/view/customer_welcome_page.dart';
import 'package:aitrainer_app/view/evaluation_page.dart';
import 'package:aitrainer_app/view/exercise_control_page.dart';
import 'package:aitrainer_app/view/exercise_execute_page.dart';
import 'package:aitrainer_app/view/exercise_execute_plan_add_page.dart';
import 'package:aitrainer_app/view/exercise_log_page.dart';
import 'package:aitrainer_app/view/exercise_plan_custom_page.dart';
import 'package:aitrainer_app/view/exercise_plan_custom_detail_add_page.dart';
import 'package:aitrainer_app/view/faq_page.dart';
import 'package:aitrainer_app/view/login.dart';
import 'package:aitrainer_app/view/exercise_new_page.dart';
import 'package:aitrainer_app/view/my_training_plans_page.dart';
import 'package:aitrainer_app/view/mydevelopment_body_page.dart';
import 'package:aitrainer_app/view/mydevelopment_muscle_page.dart';
import 'package:aitrainer_app/view/mydevelopment_page.dart';
import 'package:aitrainer_app/view/mydevelopment_sizes_page.dart';
import 'package:aitrainer_app/view/myexcercise_plan_page.dart';
import 'package:aitrainer_app/view/registration.dart';
import 'package:aitrainer_app/view/reset_password.dart';
import 'package:aitrainer_app/view/sales_page.dart';
import 'package:aitrainer_app/view/settings.dart';
import 'package:aitrainer_app/view/test_set_control.dart';
import 'package:aitrainer_app/view/test_set_edit.dart';
import 'package:aitrainer_app/view/test_set_execute.dart';
import 'package:aitrainer_app/view/test_set_new.dart';
import 'package:aitrainer_app/view/training_plan_activate_page.dart';
import 'package:aitrainer_app/view/training_plan_execute_page.dart';
import 'package:aitrainer_app/view/training_plan_exercise.dart';
import 'package:aitrainer_app/widgets/home.dart';
import 'package:aitrainer_app/library/facebook_app_events/facebook_app_events.dart';
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_analytics/observer.dart';
import 'package:flurry/flurry.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:aitrainer_app/util/app_localization.dart';
import 'package:flutter_uxcam/flutter_uxcam.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'bloc/account/account_bloc.dart';
import 'bloc/body_development/body_development_bloc.dart';
import 'bloc/development_by_muscle/development_by_muscle_bloc.dart';
import 'bloc/exercise_execute_plan/exercise_execute_plan_bloc.dart';
import 'bloc/exercise_plan/exercise_plan_bloc.dart';
import 'bloc/menu/menu_bloc.dart';
import 'bloc/session/session_bloc.dart';
import 'bloc/settings/settings_bloc.dart';
import 'bloc/timer/timer_bloc.dart';
import 'model/cache.dart';

const dsn = 'https://0f635b7225564abc9089f8106f25eb5c@sentry.aitrainer.app/1';

/// Whether the VM is running in debug mode.
///
/// This is useful to decide whether a report should be sent to sentry. Usually
/// reports from dev mode are not very useful, as these happen on developers'
/// workspaces rather than on users' devices in production.
bool get isInDebugMode {
  bool inDebugMode = false;
  assert(inDebugMode = true);
  return inDebugMode;
}

/// Reports [error] along with its [stackTrace] to Sentry.io.
Future<Null> _reportError(dynamic error, dynamic stackTrace) async {
  print('Caught error: $error');

  // Errors thrown in development mode are unlikely to be interesting. You can
  // check if you are running in dev mode using an assertion and omit sending
  // the report.
  if (isInDebugMode) {
    print(stackTrace);
    print('In dev mode. Not sending report to Sentry.io.');
    return;
  }

  print('Reporting to Sentry.io...');
  final String customerId = Cache().userLoggedIn != null ? Cache().userLoggedIn!.customerId.toString() : "0";
  Sentry.configureScope(
    (scope) => scope.user = SentryUser(id: customerId),
  );
  final String platform = Platform.isAndroid ? "Android" : "iOS";
  final String version = Cache().packageInfo != null ? Cache().packageInfo!.version + "+" + Cache().packageInfo!.buildNumber : "";
  final sentryId =
      await Sentry.captureException(error, stackTrace: stackTrace, hint: "Platform: $platform, Version: $version, User: $customerId");

  print('Capture exception result : SentryId : $sentryId');
}

Future<Null> main() async {
  // This captures errors reported by the Flutter framework.
  FlutterError.onError = (FlutterErrorDetails details) async {
    if (isInDebugMode) {
      // In development mode simply print to console.
      FlutterError.dumpErrorToConsole(details);
    } else {
      // In production mode report to the application zone to report to
      // Sentry.
      Zone.current.handleUncaughtError(details.exception, details.stack!);
    }
  };

  // This creates a [Zone] that contains the Flutter application and stablishes
  // an error handler that captures errors and reports them.
  //
  // Using a zone makes sure that as many errors as possible are captured,
  // including those thrown from [Timer]s, microtasks, I/O, and those forwarded
  // from the `FlutterError` handler.
  //
  // More about zones:
  //
  // - https://api.dartlang.org/stable/1.24.2/dart-async/Zone-class.html
  // - https://www.dartlang.org/articles/libraries/zones
  runZonedGuarded<Future<Null>>(() async {
    if (!isInDebugMode) {
      await SentryFlutter.init(
        (options) {
          options.dsn = dsn;
          options.release = Cache().packageInfo != null ? Cache().packageInfo!.version + "+" + Cache().packageInfo!.buildNumber : "";
          options.enableAutoSessionTracking = true;
        },
      );
    }

    final WorkoutTreeRepository menuTreeRepository = WorkoutTreeRepository();
    WidgetsFlutterBinding.ensureInitialized();
    if (!isInDebugMode) {
      FlutterUxcam.startWithKey("wvdstyoml4tiwfd");
    }

    print(" -- FireBase init..");
    await FirebaseApi().initializeFlutterFire();

    runApp(MultiBlocProvider(
      providers: [
        BlocProvider<SessionBloc>(
          create: (BuildContext context) => SessionBloc(session: Session()),
        ),
        BlocProvider<MenuBloc>(
          create: (BuildContext context) => MenuBloc(menuTreeRepository: menuTreeRepository),
        ),
        BlocProvider<SettingsBloc>(
          create: (BuildContext context) => SettingsBloc(context: context),
        ),
        BlocProvider<AccountBloc>(
          create: (BuildContext context) => AccountBloc(customerRepository: CustomerRepository()),
        ),
        BlocProvider<ExercisePlanBloc>(
          create: (BuildContext context) => ExercisePlanBloc(menuTreeRepository: menuTreeRepository),
        ),
        BlocProvider<ExerciseExecutePlanBloc>(
          create: (BuildContext context) => ExerciseExecutePlanBloc(menuTreeRepository: menuTreeRepository),
        ),
        BlocProvider<DevelopmentByMuscleBloc>(
          create: (BuildContext context) => DevelopmentByMuscleBloc(workoutTreeRepository: menuTreeRepository),
        ),
        BlocProvider<BodyDevelopmentBloc>(
          create: (BuildContext context) => BodyDevelopmentBloc(workoutTreeRepository: menuTreeRepository),
        ),
        BlocProvider<TimerBloc>(
          create: (BuildContext context) => TimerBloc(),
        ),
        BlocProvider<TestSetExecuteBloc>(
          create: (BuildContext context) => TestSetExecuteBloc(),
        ),
        BlocProvider<TutorialBloc>(create: (BuildContext context) => TutorialBloc(tutorialName: ActivityDone.tutorialBasic.toStr())),
        BlocProvider<TrainingPlanBloc>(create: (context) {
          final MenuBloc menuBloc = BlocProvider.of<MenuBloc>(context);
          return TrainingPlanBloc(menuBloc: menuBloc, trainingPlanRepository: TrainingPlanRepository());
        }),
      ],
      child: WorkoutTestApp(),
    ));
  }, (error, stackTrace) async {
    await _reportError(error, stackTrace);
  });
}

Future<void> initThirdParty() async {
  if (!isInDebugMode) {
    await Flurry.initialize(androidKey: "JNYCTCWBT34FM3J8TV36", iosKey: "3QBG7BSMGPDH24S8TRQP", enableLog: true);
    FlutterUxcam.optIntoSchematicRecordings();
    PushNotificationsManager().init();
  }
}

class WorkoutTestApp extends StatelessWidget {
  static final facebookAppEvents = FacebookAppEvents();
  @override
  Widget build(BuildContext context) {
    SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
    final FirebaseAnalytics analytics = FirebaseAnalytics();

    //facebookAppEvents.setAdvertiserTracking(enabled: true);
    initThirdParty();
    return MaterialApp(
      localizationsDelegates: [
        // ... app-specific localization delegate[s] here
        AppLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: [
        const Locale('en', "US"), // English
        const Locale('hu', "HU"), // Hungarian
        // ... other locales the app supports
      ],
      localeResolutionCallback: (Locale? locale, Iterable<Locale> supportedLocales) {
        //myLocale = deviceLocale ;
        // here you make your app language similar to device language ,
        // but you should check whether the localization is supported by your app
        Locale realSupportedLocale = Locale('en', "US");
        supportedLocales.forEach((supportedLocale) {
          if (locale != null && supportedLocale.countryCode == locale.countryCode) {
            realSupportedLocale = supportedLocale;
          }
        });
        if (locale != null && realSupportedLocale.countryCode != locale.countryCode) {
          //print ("Locale " + locale.countryCode + " not supported on this device :(");
        }
        return realSupportedLocale;
      },
      routes: {
        'home': (context) => AitrainerHome(),
        'customerModifyPage': (context) => CustomerModifyPage(),
        'customerGoalPage': (context) => CustomerGoalPage(),
        'customerFitnessPage': (context) => CustomerFitnessPage(),
        'customerBodyTypePage': (context) => CustomerBodyTypeAnimationPage(),
        'customerWelcomePage': (context) => CustomerWelcomePage(),
        'customerExerciseDevicePage': (context) => CustomerExerciseDevicePage(),
        'exerciseNewPage': (context) => ExerciseNewPage(),
        'exerciseControlPage': (context) => ExerciseControlPage(),
        'login': (context) => LoginPage(),
        'resetPassword': (context) => ResetPasswordPage(),
        'registration': (context) => RegistrationPage(),
        'account': (context) => AccountPage(),
        'settings': (context) => SettingsPage(),
        'myDevelopment': (context) => MyDevelopmentPage(),
        'myExercisePlan': (context) => MyExercisePlanPage(),
        'exerciseLogPage': (context) => ExerciseLogPage(),
        'exercisePlanCustomPage': (context) => ExercisePlanCustomPage(),
        'exercisePlanDetailAdd': (context) => ExercisePlanDetailAddPage(),
        'exerciseExecutePlanPage': (context) => ExerciseExecutePage(),
        'exerciseExecuteAddPage': (context) => ExerciseExecutePlanAddPage(),
        'mydevelopmentMusclePage': (context) => MyDevelopmentMusclePage(),
        'mydevelopmentBodyPage': (context) => MyDevelopmentBodyPage(),
        'mydevelopmentSizesPage': (context) => SizesDevelopmentPage(),
        'evaluationPage': (context) => EvaluationPage(),
        'salesPage': (context) => SalesPage(),
        'testSetEdit': (context) => TestSetEdit(),
        'testSetExecute': (context) => TestSetExecute(),
        'testSetNew': (context) => TestSetNew(),
        'testSetControl': (context) => TestSetControl(),
        'faqPage': (context) => FaqPage(),
        'myTrainingPlans': (context) => MyTrainingPlans(),
        'myTrainingPlanActivate': (context) => TrainingPlanActivatePage(),
        'myTrainingPlanExecute': (context) => TrainingPlanExecutePage(),
        'myTrainingPlanExercise': (context) => TrainingPlanExercise(),
      },
      initialRoute: 'home',
      title: 'WorkoutTest',
      theme: ThemeData(
          brightness: Brightness.light,
          //primarySwatch: Colors.transparent,
          //fontFamily: 'Arial',
          textTheme: TextTheme(
            bodyText1: GoogleFonts.inter(textStyle: TextStyle(fontSize: 14.0)),
          )),
      navigatorObservers: [
        FirebaseAnalyticsObserver(analytics: analytics),
      ],
      home: AitrainerHome(),
    );
  }
}
