import 'dart:collection';
import 'dart:ui';
import 'package:aitrainer_app/bloc/training_plan/training_plan_bloc.dart';
import 'package:aitrainer_app/bloc/tutorial/tutorial_bloc.dart';
import 'package:aitrainer_app/model/exercise_ability.dart';
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/util/enums.dart';
import 'package:aitrainer_app/util/track.dart';
import 'package:aitrainer_app/widgets/menu_image.dart';
import 'package:aitrainer_app/widgets/menu_search_bar.dart';
import 'package:aitrainer_app/util/app_language.dart';
import 'package:aitrainer_app/util/app_localization.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/workout_menu_tree.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/dialog_common.dart';
import 'package:aitrainer_app/widgets/tutorial_widget.dart';
import 'package:badges/badges.dart';
import 'package:ezanimation/ezanimation.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:google_fonts/google_fonts.dart';

import 'dialog_html.dart';

// ignore: must_be_immutable
class MenuPageWidget extends StatefulWidget {
  int? parent;

  MenuPageWidget({this.parent});

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

class _MenuPageWidgetState extends State<MenuPageWidget> with Trans, Logging {
  final double baseWidth = 312;
  final double baseHeight = 675.2;
  late MenuBloc menuBloc;
  late TutorialBloc tutorialBloc;
  final scrollController = ScrollController();
  final bool activeExercisePlan = Cache().activeExercisePlan != null;
  final EzAnimation animation = EzAnimation(35.0, 10.0, Duration(seconds: 2), reverseCurve: Curves.linear);

  @override
  void initState() {
    if (activeExercisePlan || Cache().myTrainingPlan != null) {
      animation.start();
      animation.addStatusListener((status) {
        if (status == AnimationStatus.completed || status == AnimationStatus.dismissed) {
          animation.reverse();
        }
      });
      animation.addListener(() {});
    }

    /// We require the initializers to run after the loading screen is rendered
    SchedulerBinding.instance!.addPostFrameCallback((_) {
      menuBloc.add(MenuCreate());
      //runDelayedEvent();
    });

    super.initState();
  }

  Future runDelayedEvent() async {
    bool isFirst = false;
    await Future.delayed(Duration(milliseconds: 600), () async {
      if (Cache().userLoggedIn != null) {
        if (Cache().userLoggedIn!.sex == "m") {
          tutorialBloc.tutorialName = ActivityDone.tutorialBasicChestPress.toStr();
        } else {
          tutorialBloc.tutorialName = ActivityDone.tutorialBasicLegPress.toStr();
        }
      }
      if (!tutorialBloc.isTutorialDone()) {
        if (tutorialBloc.isActive == false && tutorialBloc.canActivate) {
          tutorialBloc.canActivate = true;
          tutorialBloc.isActive = true;
          tutorialBloc.menuBloc = menuBloc;
          tutorialBloc.add(TutorialLoad());
          tutorialBloc.init();
          isFirst = true;
        }
      }
    });
    final bool canActivate = tutorialBloc.activateTutorial();
    if (canActivate) {
      if (!isFirst) {
        TutorialWidget().tip(context);
      }
    }
  }

  @override
  bool didUpdateWidget(MenuPageWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    scrollController.animateTo(5, duration: Duration(milliseconds: 300), curve: Curves.easeIn);
    runDelayedEvent();
    return true;
  }

  @override
  Widget build(BuildContext context) {
    menuBloc = BlocProvider.of<MenuBloc>(context);
    tutorialBloc = BlocProvider.of<TutorialBloc>(context);
    setContext(context);
    double cWidth = MediaQuery.of(context).size.width;
    double cHeight = MediaQuery.of(context).size.height;

    if (widget.parent == null) {
      widget.parent = 0;
    }

    return Stack(children: [
      CustomScrollView(
          controller: scrollController,
          scrollDirection: Axis.vertical,
          slivers: buildMenuColumn(widget.parent!, context, menuBloc, cWidth, cHeight)),
    ]);
  }

  List<Widget> buildMenuColumn(int parent, BuildContext context, MenuBloc menuBloc, double cWidth, double cHeight) {
    final List<Widget> slivers = [];

    bool isChild = menuBloc.menuTreeRepository.isChildAndGym(menuBloc.parent);
    if (!isChild) {
      slivers.add(getInfoWidget(context, menuBloc));
    } else {
      slivers.add(getFilterWidget(parent, menuBloc));
      slivers.add(getFilterElements(menuBloc));
    }

    final List<Widget> _columnChildren = [];

    if (menuBloc.getFilteredBranch(menuBloc.parent).isEmpty) {
      _columnChildren.add(Container(
          padding: EdgeInsets.only(top: 15.0),
          child: Center(
              child: Stack(alignment: Alignment.bottomLeft, children: [
            Text(AppLocalizations.of(context)!.translate("All Exercises has been filtered out"),
                style: GoogleFonts.inter(color: Colors.white)),
          ]))));
    } else {
      menuBloc.getFilteredBranch(menuBloc.parent).forEach((treeName, value) {
        WorkoutMenuTree workoutTree = value;
        _columnChildren.add(Container(
            padding: EdgeInsets.only(top: 15.0, left: cWidth * 0.04, right: cWidth * 0.04),
            //height: (cHeight / 3) - cWidth * 0.16,
            child: Badge(
                padding: EdgeInsets.all(8),
                position: BadgePosition.bottomEnd(end: 0),
                animationDuration: Duration(milliseconds: 500),
                animationType: BadgeAnimationType.slide,
                badgeColor: Colors.orange[800]!,
                showBadge: workoutTree.base,
                badgeContent: Text(AppLocalizations.of(context)!.translate("base"),
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 12,
                    )),
                child: Badge(
                    showBadge: workoutTree.nameEnglish == "One Rep Max" || workoutTree.nameEnglish == "Endurance",
                    animationDuration: Duration(milliseconds: 800),
                    animationType: BadgeAnimationType.fade,
                    badgeColor: Colors.blue[100]!,
                    badgeContent: GestureDetector(
                        onTap: () => {
                              showDialog(
                                  context: context,
                                  builder: (BuildContext context) {
                                    return DialogHTML(
                                      title: workoutTree.name,
                                      htmlData: workoutTree.nameEnglish == "Endurance"
                                          ? AppLocalizations.of(context)!.translate("Endurance_desc")
                                          : AppLocalizations.of(context)!.translate("OneRepMax_desc"),
                                    );
                                  })
                            },
                        child: Icon(Icons.info_outline_rounded)),
                    child: Stack(alignment: Alignment.bottomLeft, children: [
                      TextButton(
                        child: badgedIcon(workoutTree, cWidth, cHeight),
                        onPressed: () => menuClick(workoutTree, menuBloc),
                      ),
                      Container(
                        padding: EdgeInsets.only(left: 15, bottom: 8, right: 15),
                        child: GestureDetector(
                          onTap: () => menuClick(workoutTree, menuBloc),
                          child: Text(
                            workoutTree.name,
                            maxLines: 4,
                            style: GoogleFonts.archivoBlack(color: workoutTree.color, fontSize: workoutTree.fontSize, height: 1.1),
                          ),
                        ),
                      ),
                    ])))));
      });
    }

    SliverList sliverList = SliverList(
      delegate: SliverChildListDelegate(_columnChildren),
    );
    slivers.add(sliverList);
    return slivers;
  }

  SliverGrid getFilterWidget(int parent, MenuBloc menuBloc) {
    SliverGrid sliverList = SliverGrid(
        delegate: SliverChildListDelegate([
          Column(mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [
            Text(
              AppLocalizations.of(context)!.translate("Equipment Filter"),
              textAlign: TextAlign.center,
              style: GoogleFonts.archivoBlack(
                fontSize: 24,
                color: Colors.white,
                shadows: <Shadow>[
                  Shadow(
                    offset: Offset(5.0, 5.0),
                    blurRadius: 12.0,
                    color: Colors.black54,
                  ),
                  Shadow(
                    offset: Offset(-3.0, 3.0),
                    blurRadius: 12.0,
                    color: Colors.black54,
                  ),
                ],
              ),
            ),
          ])
        ]),
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 1,
          mainAxisSpacing: 5.0,
          crossAxisSpacing: 5.0,
          childAspectRatio: 9,
        ));

    return sliverList;
  }

  SliverGrid getFilterElements(MenuBloc menuBloc) {
    List<Widget> list = [];

    int index = 0;
    menuBloc.exerciseDeviceRepository.getGymDevices().forEach((element) {
      String deviceName = AppLanguage().appLocal == Locale('en') ? element.name : element.nameTranslation;
      ChoiceChip chip = ChoiceChip(
        labelPadding: EdgeInsets.only(right: 3),
        avatar: Icon(
          Icons.remove_circle_outline,
          color: Colors.orange,
          size: 10,
        ),
        label: Text(deviceName),
        labelStyle: TextStyle(fontSize: 9, color: Colors.indigo),
        selectedColor: Colors.white,
        selected: menuBloc.selectedDevice(element.exerciseDeviceId),
        backgroundColor: Colors.blue[100],
        shadowColor: Colors.black54,
        onSelected: (value) => menuBloc.add(MenuFilterExerciseType(deviceId: element.exerciseDeviceId)),
      );
      list.add(chip);
      if (index == 4) {
        list.add(Divider());
      }

      index++;
    });

    SliverGrid sliverList = SliverGrid(
        delegate: SliverChildListDelegate(list),
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 4,
          mainAxisSpacing: 1.5,
          crossAxisSpacing: 1.5,
          childAspectRatio: 2.5,
        ));
    return sliverList;
  }

  SliverAppBar getInfoWidget(BuildContext context, MenuBloc menuBloc) {
    menuBloc.setContext(context);

    SliverAppBar sliverAppBar = SliverAppBar(
        automaticallyImplyLeading: false,
        backgroundColor: Colors.transparent,
        title: Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
          !activeExercisePlan
              ? SizedBox(
                  width: 50,
                )
              : SizedBox(
                  width: 10,
                ),
          MenuSearchBar(
            listItems: menuBloc.menuTreeRepository.menuAsExercise,
            onFind: (value) {
              if (Cache().userLoggedIn == null) {
                ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                    backgroundColor: Colors.orange,
                    content: Text(AppLocalizations.of(context)!.translate('Please log in'), style: TextStyle(color: Colors.white))));
              } else {
                Track().track(TrackingEvent.search, eventValue: value.exerciseType!.name);
                menuBloc.ability = ExerciseAbility.oneRepMax;
                Navigator.of(context).popAndPushNamed('exerciseNewPage', arguments: value.exerciseType);
              }
            },
          ),
          Cache().myTrainingPlan != null
              ? GestureDetector(
                  onTap: () => showDialog(
                      context: context,
                      builder: (BuildContext context) {
                        return DialogCommon(
                          title: t("You have an active Training Plan"),
                          descriptions: Cache().myTrainingPlan!.name != null ? Cache().myTrainingPlan!.name! : "",
                          description2: t("Press OK to continue"),
                          text: "OK",
                          onTap: () {
                            Navigator.of(context).pop();
                            if (Cache().myTrainingPlan != null) {
                              final TrainingPlanBloc bloc = BlocProvider.of<TrainingPlanBloc>(context);
                              bloc.setMyPlan(Cache().myTrainingPlan);
                              Navigator.of(context).popAndPushNamed("myTrainingPlanExecute");
                            }
                          },
                          onCancel: () => {
                            Navigator.of(context).pop(),
                          },
                        );
                      }),
                  child: AnimatedBuilder(
                      animation: animation,
                      builder: (context, snapshot) {
                        return Center(
                          child: Container(
                            width: animation.value,
                            height: animation.value,
                            child: Image.asset("asset/image/pict_hypertrophy.png"),
                          ),
                        );
                      }))
              : Offstage(),
          /* activeExercisePlan
              ? SizedBox(
                  width: 10,
                )
              : Offstage(), */
          Cache().activeExercisePlan != null
              ? GestureDetector(
                  onTap: () => showDialog(
                      context: context,
                      builder: (BuildContext context) {
                        return DialogCommon(
                          title: t("You have an active Test Set!"),
                          descriptions: Cache().activeExercisePlan!.name,
                          description2: t("Press OK to continue"),
                          text: "OK",
                          onTap: () => {
                            Navigator.of(context).pop(),
                            if (Cache().activeExercisePlan != null)
                              {
                                Navigator.of(context).popAndPushNamed("testSetExecute"),
                              }
                          },
                          onCancel: () => {
                            Navigator.of(context).pop(),
                          },
                        );
                      }),
                  child: AnimatedBuilder(
                      animation: animation,
                      builder: (context, snapshot) {
                        return Center(
                          child: Container(
                            width: animation.value,
                            height: animation.value,
                            child: Image.asset("asset/image/pict_reps_volumen_db.png"),
                          ),
                        );
                      }))
              : Offstage(),
          activeExercisePlan
              ? SizedBox(
                  width: 10,
                )
              : Offstage(),
        ]));
    return sliverAppBar;
  }

  void menuClick(WorkoutMenuTree workoutTree, MenuBloc menuBloc) {
    if (tutorialBloc.isActive) {
      final String checkText = workoutTree.nameEnglish;
      if (!tutorialBloc.checkAction(checkText)) {
        return;
      }
    }
    if (workoutTree.child == false) {
      if (menuBloc.ability != null && ExerciseAbility.mini_test_set.equalsTo(menuBloc.ability!) && workoutTree.parent != 0) {
        HashMap args = HashMap();
        args['templateName'] = workoutTree.nameEnglish;
        args['templateNameTranslation'] = workoutTree.name;
        Navigator.of(context).pushNamed('testSetEdit', arguments: args);
      } else if (menuBloc.ability != null && ExerciseAbility.training.equalsTo(menuBloc.ability!) && workoutTree.parent != 0) {
        HashMap<String, dynamic> args = HashMap();
        args['parentName'] = workoutTree.internalName;
        Navigator.of(context).pushNamed("myTrainingPlanActivate", arguments: args);
      }
      menuBloc.add(MenuTreeDown(item: workoutTree, parent: workoutTree.id));
    } else {
      menuBloc.add(MenuClickExercise(exerciseTypeId: workoutTree.id));

      if (workoutTree.exerciseType!.name == "Custom" && Cache().userLoggedIn!.admin == 1) {
        Navigator.of(context).pushNamed('exerciseCustomPage', arguments: workoutTree.exerciseType);
      } else {
        Navigator.of(context).pushNamed('exerciseNewPage', arguments: workoutTree.exerciseType);
      }
    }
  }

  dynamic getShape(WorkoutMenuTree workoutTree) {
    bool base = workoutTree.base;
    dynamic returnCode = (base == true)
        ? RoundedRectangleBorder(
            side: BorderSide(width: 6, color: Colors.orangeAccent), borderRadius: BorderRadius.all(Radius.circular(24.0)))
        : RoundedRectangleBorder(
            side: BorderSide(width: 1, color: Colors.transparent), borderRadius: BorderRadius.all(Radius.circular(8.0)));
    return returnCode;
  }

  Widget badgedIcon(WorkoutMenuTree workoutMenuTree, double cWidth, double cHeight) {
    String badgeKey = workoutMenuTree.nameEnglish;
    bool show = Cache().getBadges()[badgeKey] != null;
    int counter = Cache().getBadges()[badgeKey] != null ? Cache().getBadges()[badgeKey] : 0;
    Widget buttonImage = MenuImage(imageName: workoutMenuTree.imageName, workoutTreeId: workoutMenuTree.id);
    return Badge(
      padding: EdgeInsets.all(8),
      position: BadgePosition.topEnd(top: 3, end: 3),
      animationDuration: Duration(milliseconds: 500),
      animationType: BadgeAnimationType.slide,
      badgeColor: Colors.red,
      showBadge: show,
      badgeContent: Text(counter.toString(),
          style: TextStyle(
            color: Colors.white,
            fontSize: 16,
          )),
      child: buttonImage,
    );
  }

  @override
  void dispose() {
    scrollController.dispose();
    super.dispose();
  }
}