import 'dart:collection';

import 'package:aitrainer_app/bloc/training_plan/training_plan_bloc.dart';
import 'package:aitrainer_app/library/custom_icon_icons.dart';
import 'package:aitrainer_app/model/customer_training_plan_details.dart';
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
import 'package:aitrainer_app/util/app_localization.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/dialog_common.dart';
import 'package:aitrainer_app/widgets/menu_image.dart';
import 'package:extended_tabs/extended_tabs.dart';
import 'package:ezanimation/ezanimation.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
import 'package:timeline_tile/timeline_tile.dart';

// ignore: must_be_immutable
class TrainingPlanExecutePage extends StatefulWidget {
  @override
  _TrainingPlanExecutePageState createState() => _TrainingPlanExecutePageState();
}

class _TrainingPlanExecutePageState extends State<TrainingPlanExecutePage> with Trans {
  final scrollController = ScrollController();
  TrainingPlanBloc? bloc;

  @override
  Widget build(BuildContext context) {
    bloc = BlocProvider.of<TrainingPlanBloc>(context);
    bloc!.activateDays();
    setContext(context);
    return Scaffold(
      appBar: AppBarNav(depth: 0),
      body: Container(
        padding: EdgeInsets.all(20),
        decoration: BoxDecoration(
          image: DecorationImage(
            image: AssetImage('asset/image/WT_black_background.jpg'),
            fit: BoxFit.cover,
            alignment: Alignment.center,
          ),
        ),
        child: BlocConsumer<TrainingPlanBloc, TrainingPlanState>(listener: (context, state) {
          if (state is TrainingPlanError) {
            ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
          } else if (state is TrainingPlanFinished) {}
        }, builder: (context, state) {
          return ModalProgressHUD(
            child: ExerciseTabs(bloc: bloc!),
            inAsyncCall: state is TrainingPlanLoading,
            opacity: 0.5,
            color: Colors.black54,
            progressIndicator: CircularProgressIndicator(),
          );
        }),
      ),
      floatingActionButton: FloatingActionButton.extended(
        onPressed: () => bloc!.getNext() != null
            ? _ExerciseListState.executeExercise(bloc!, bloc!.getNext()!, context)
            : Navigator.of(context).pushNamed('home'),
        backgroundColor: Colors.orange[800],
        icon: Icon(CustomIcon.weight_hanging),
        label: Text(
          t("Training!"),
          style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 16),
        ),
      ),
    );
  }
}

class ExerciseTabs extends StatefulWidget {
  final TrainingPlanBloc bloc;
  ExerciseTabs({required this.bloc});
  @override
  _ExerciseTabs createState() => _ExerciseTabs();
}

class _ExerciseTabs extends State<ExerciseTabs> with TickerProviderStateMixin {
  late TabController tabController;

  @override
  void initState() {
    super.initState();
    tabController = TabController(length: widget.bloc.dayNames.length, vsync: this);
    tabController.animateTo(0, duration: Duration(milliseconds: 300));
  }

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

  @override
  Widget build(BuildContext context) {
    return getTabs(widget.bloc);
  }

  Widget getTabs(TrainingPlanBloc bloc) {
    return Column(children: [
      ExtendedTabBar(
        tabs: getTabNames(),
        controller: tabController,
      ),
      Expanded(
          child: ExtendedTabBarView(
        children: getExerciseLists(),
        controller: tabController,

        /// if link is true and current tabbarview over scroll,
        /// it will check and scroll ancestor or child tabbarView.
        link: true,

        /// cache page count
        /// default is 0.
        /// if cacheExtent is 1, it has two pages in cache
        /// null is infinity, it will cache all pages
        cacheExtent: 0,
      )),
    ]);
  }

  List<Tab> getTabNames() {
    List<Tab> tabs = [];
    widget.bloc.dayNames.forEach((element) {
      final Widget widget = RichText(
          text: TextSpan(
              style: GoogleFonts.inter(
                fontSize: 14,
                fontWeight: FontWeight.bold,
                color: Colors.white,
              ),
              children: [
            TextSpan(
                text: AppLocalizations.of(context)!.translate("Training Day") + ": \n",
                style: GoogleFonts.inter(
                  fontSize: 14,
                  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,
                    ),
                  ],
                )),
            TextSpan(
                text: element,
                style: GoogleFonts.inter(
                  fontSize: 14,
                  fontWeight: FontWeight.bold,
                  color: Colors.yellow[400],
                  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,
                    ),
                  ],
                )),
          ]));

      tabs.add(Tab(child: widget));
    });
    return tabs;
  }

  List<Widget> getExerciseLists() {
    List<Widget> list = [];
    widget.bloc.dayNames.forEach((element) {
      list.add(ExerciseList(bloc: widget.bloc, dayName: element));
    });
    return list;
  }
}

class ExerciseList extends StatefulWidget {
  final TrainingPlanBloc bloc;
  final String dayName;
  ExerciseList({required this.bloc, required this.dayName});

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

class _ExerciseListState extends State<ExerciseList> with Trans {
  final scrollController = ScrollController();
  double offset = 5;

  @override
  void initState() {
    WidgetsBinding.instance!.addPostFrameCallback((_) {
      animate();
    });
    super.initState();
  }

  @override
  void didUpdateWidget(ExerciseList page) {
    super.didUpdateWidget(page);
    WidgetsBinding.instance!.addPostFrameCallback((_) {
      animate();
    });
  }

  void animate() {
    offset = widget.bloc.getOffset();
    if (scrollController.hasClients) {
      scrollController.animateTo(offset, duration: Duration(milliseconds: 300), curve: Curves.easeIn);
    }
  }

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

  @override
  Widget build(BuildContext context) {
    setContext(context);
    return CustomScrollView(controller: scrollController, slivers: [
      SliverList(delegate: SliverChildListDelegate(getTiles(widget.bloc))),
    ]);
  }

  List<Widget> getTiles(TrainingPlanBloc bloc) {
    List<Widget> tiles = [];
    tiles.add(getStartTile(bloc));
    tiles.addAll(getExerciseTiles(bloc, context));
    if (bloc.getMyPlan() != null) tiles.add(getEndTile());
    return tiles;
  }

  Widget getStartTile(TrainingPlanBloc bloc) {
    String startText = "";
    String explainingText = "";
    if (null == bloc.getMyPlan()) {
      startText = t("No Active Training Plan");
      explainingText = t("Please select one in the Training menu, or create your custom plan");
    } else {
      startText = bloc.isStarted() ? t("Continue your training") : t("Start your training");
      explainingText = bloc.getMyPlan()!.name != null ? bloc.getMyPlan()!.name! : "";
      print(" *** Plan NAME ${bloc.getMyPlan()!.name}");
    }

    return TimelineTile(
      alignment: TimelineAlign.manual,
      lineXY: 0.1,
      isFirst: true,
      afterLineStyle: const LineStyle(
        color: Colors.orange,
        thickness: 6,
      ),
      indicatorStyle: IndicatorStyle(
        width: 40,
        color: Colors.orange,
        padding: const EdgeInsets.all(8),
        iconStyle: IconStyle(
          color: Colors.white,
          iconData: Icons.emoji_flags_rounded,
        ),
      ),
      endChild: Container(
        padding: EdgeInsets.only(top: 30),
        constraints: const BoxConstraints(
          minHeight: 120,
        ),
        color: Colors.transparent,
        child: RichText(
            text: TextSpan(
                style: GoogleFonts.inter(
                  fontSize: 14,
                  fontWeight: FontWeight.bold,
                  color: Colors.white,
                ),
                children: [
              TextSpan(
                  text: startText,
                  style: GoogleFonts.inter(
                    fontSize: 20,
                    fontWeight: FontWeight.bold,
                    color: Colors.yellow[400],
                    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,
                      ),
                    ],
                  )),
              TextSpan(
                  text: "\n",
                  style: GoogleFonts.inter(
                    fontSize: 16,
                    color: Colors.white,
                  )),
              TextSpan(
                  text: explainingText,
                  style: GoogleFonts.inter(
                    fontSize: 16,
                    color: Colors.white,
                  )),
            ])),
      ),
    );
  }

  Widget getEndTile() {
    return Container(
      color: Colors.transparent,
      child: TimelineTile(
        alignment: TimelineAlign.manual,
        lineXY: 0.1,
        isLast: true,
        beforeLineStyle: const LineStyle(
          color: Colors.orange,
          thickness: 6,
        ),
        indicatorStyle: IndicatorStyle(
          width: 40,
          color: Colors.orange,
          padding: const EdgeInsets.all(8),
          iconStyle: IconStyle(
            color: Colors.white,
            iconData: Icons.thumb_up,
          ),
        ),
        endChild: Container(
          padding: EdgeInsets.only(top: 50),
          constraints: const BoxConstraints(
            minHeight: 120,
          ),
          color: Colors.transparent,
          child: RichText(
              text: TextSpan(
                  style: GoogleFonts.inter(
                    fontSize: 14,
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                  ),
                  children: [
                TextSpan(
                    text: "Finish!",
                    style: GoogleFonts.inter(
                      fontSize: 20,
                      fontWeight: FontWeight.bold,
                      color: Colors.yellow[400],
                      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,
                        ),
                      ],
                    )),
              ])),
        ),
      ),
    );
  }

  List<Widget> getExerciseTiles(TrainingPlanBloc bloc, BuildContext context) {
    List<Widget> tiles = [];
    if (bloc.getMyPlan() != null &&
        bloc.getMyPlan()!.details.isNotEmpty &&
        bloc.getMyPlan()!.days[widget.dayName] != null &&
        bloc.getMyPlan()!.days[widget.dayName]!.isNotEmpty) {
      bloc.getMyPlan()!.days[widget.dayName]!.forEach((element) {
        //bloc.getMyPlan()!.details.forEach((element) {
        tiles.add(GestureDetector(
            onTap: () => bloc.getNext() != null ? executeExercise(bloc, bloc.getNext()!, context) : Navigator.of(context).pushNamed('home'),
            child: ExerciseTile(
              bloc: bloc,
              detail: element,
            )));
      });
    }

    return tiles;
  }

  static void executeExercise(TrainingPlanBloc bloc, CustomerTrainingPlanDetails detail, BuildContext context) {
    CustomerTrainingPlanDetails? next = bloc.getNext();

    if (next != null) {
      String title = "";
      String description = "";
      String description2 = "";
      if (next.exerciseTypeId != detail.exerciseTypeId) {
        title = AppLocalizations.of(context)!.translate("Stop!");
        description = AppLocalizations.of(context)!.translate("Please continue with the next exercise in the queue:") +
            next.exerciseType!.nameTranslation;
        description2 = AppLocalizations.of(context)!.translate("Or, you can redifine this exercise queue in the Compact Test menu");
      } else {
        final HashMap args = HashMap();
        args['exerciseType'] = next.exerciseType;
        args['customerTrainingPlanDetails'] = detail;
        Navigator.of(context).pushNamed('myTrainingPlanExercise', arguments: args);
        return;
      }

      showDialog(
          context: context,
          barrierDismissible: false,
          builder: (BuildContext context) {
            return DialogCommon(
              title: title,
              descriptions: description,
              description2: description2,
              text: "OK",
              onTap: () => {Navigator.of(context).pop()},
              onCancel: () => {Navigator.of(context).pop()},
            );
          });
    } else {
      Navigator.of(context).pushNamed('home');
    }
  }
}

class ExerciseTile extends StatefulWidget {
  final TrainingPlanBloc bloc;
  final CustomerTrainingPlanDetails detail;

  ExerciseTile({required this.bloc, required this.detail});

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

class _ExerciseTileState extends State<ExerciseTile> with Trans {
  final EzAnimation animation = EzAnimation(1.0, 30.0, Duration(seconds: 3), reverseCurve: Curves.easeIn);

  @override
  void initState() {
    animation.start();
    animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {}
    });

    super.initState();
  }

  @override
  bool didUpdateWidget(ExerciseTile oldWidget) {
    super.didUpdateWidget(oldWidget);
    Future.delayed(Duration(milliseconds: 400)).then((value) => animation.start());
    return true;
  }

  Widget getIndicator(ExercisePlanDetailState state) {
    CustomerTrainingPlanDetails? next = widget.bloc.getNext();
    bool actual = false;
    if (next != null) {
      if (next.exerciseTypeId == widget.detail.exerciseTypeId) {
        actual = true;
      }
    }
    if (state.equalsTo(ExercisePlanDetailState.inProgress)) {
      return ClipRRect(
          borderRadius: BorderRadius.circular(24.0),
          child: Container(
              color: actual ? Colors.green : Colors.orange,
              child: Icon(
                CustomIcon.calendar_2,
                size: 28,
                color: Colors.white,
              )));
    } else if (state.equalsTo(ExercisePlanDetailState.finished)) {
      return ClipRRect(
          borderRadius: BorderRadius.circular(24.0),
          child: Container(
              color: Colors.white,
              child: Icon(
                CustomIcon.ok_circled,
                size: 40,
                color: Colors.green,
              )));
    } else if (state.equalsTo(ExercisePlanDetailState.skipped)) {
      return ClipRRect(
          borderRadius: BorderRadius.circular(24.0),
          child: Container(
              color: Colors.white,
              child: Icon(
                CustomIcon.stop_1,
                size: 40,
                color: Colors.grey,
              )));
    } else {
      return Image.asset(
        "asset/image/pict_reps_volumen_db.png",
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    setContext(context);
    final ExercisePlanDetailState state = widget.detail.state;
    final bool done = state.equalsTo(ExercisePlanDetailState.finished) || state.equalsTo(ExercisePlanDetailState.skipped);
    final String countSerie = widget.detail.set.toString();
    final String step = (widget.detail.exercises.length).toString();
    String weight = widget.detail.weight!.toStringAsFixed(1);
    String restingTime = widget.detail.restingTime == null ? "" : widget.detail.restingTime!.toStringAsFixed(0);
    bool isTest = false;
    if (widget.detail.weight! == -1) {
      weight = t("TEST");
      isTest = true;
    }
    setContext(context);
    return Container(
      color: Colors.transparent,
      child: TimelineTile(
        alignment: TimelineAlign.manual,
        lineXY: 0.1,
        beforeLineStyle: const LineStyle(
          color: Color(0xffb4f500),
          thickness: 6,
        ),
        afterLineStyle: const LineStyle(
          color: Color(0xffb4f500),
          thickness: 6,
        ),
        indicatorStyle: IndicatorStyle(
          width: 40,
          height: 40,
          indicator: getIndicator(state),
        ),
        startChild: Container(
          child: Column(children: [
            SizedBox(
              height: 1,
            ),
            SizedBox(
              height: 55,
            ),
            done
                ? Offstage()
                : IconButton(
                    padding: EdgeInsets.zero,
                    alignment: Alignment.centerLeft,
                    icon: Icon(
                      Icons.skip_next_sharp,
                      size: 30,
                      color: Colors.orange[300],
                    ),
                    onPressed: () => skip()),
          ]),
        ),
        endChild: Container(
          padding: EdgeInsets.only(left: 10),
          child: Row(children: [
            Container(
              width: 120,
              height: 80,
              child: MenuImage(
                imageName: widget.bloc.getActualImageName(widget.detail.exerciseType!.exerciseTypeId),
                workoutTreeId: widget.bloc.getActualWorkoutTreeId(widget.detail.exerciseType!.exerciseTypeId)!,
              ),
            ),
            SizedBox(
              width: 10,
            ),
            Expanded(
                child: RichText(
              text: TextSpan(
                  style: GoogleFonts.inter(
                    fontSize: 14,
                    fontWeight: FontWeight.bold,
                    color: done ? Colors.grey[400] : Colors.white,
                  ),
                  children: [
                    TextSpan(
                        text: widget.detail.exerciseType!.nameTranslation,
                        style: GoogleFonts.inter(
                          fontSize: 14,
                          fontWeight: FontWeight.bold,
                          color: done ? Colors.grey[400] : Colors.orange[500],
                          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,
                            ),
                          ],
                        )),
                    widget.detail.exerciseType!.unitQuantityUnit != null
                        ? TextSpan(
                            text: "\n",
                          )
                        : TextSpan(),
                    widget.detail.exerciseType!.unitQuantityUnit != null
                        ? TextSpan(
                            text: t(widget.detail.exerciseType!.unitQuantityUnit!) + ": ",
                            style: GoogleFonts.inter(
                                fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold))
                        : TextSpan(),
                    widget.detail.exerciseType!.unitQuantityUnit != null
                        ? TextSpan(
                            text: weight,
                            style: GoogleFonts.inter(
                              fontSize: 12,
                            ))
                        : TextSpan(),
                    TextSpan(
                      text: "\n",
                    ),
                    TextSpan(
                        text: t(widget.detail.exerciseType!.unit) + ": ",
                        style: GoogleFonts.inter(
                            fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold)),
                    TextSpan(
                        text: widget.detail.repeats!.toString(),
                        style: GoogleFonts.inter(
                          fontSize: 12,
                        )),
                    TextSpan(
                      text: "\n",
                    ),
                    TextSpan(
                        text: t("Set") + ": ",
                        style: GoogleFonts.inter(
                            fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold)),
                    TextSpan(
                        text: step + "/" + countSerie,
                        style: GoogleFonts.inter(
                          fontSize: 12,
                        )),
                    TextSpan(
                      text: "\n",
                    ),
                    TextSpan(
                        text: t("Resting time") + ": ",
                        style: GoogleFonts.inter(
                            fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold)),
                    TextSpan(
                        text: restingTime + " " + t("min(s)"),
                        style: GoogleFonts.inter(fontSize: 12, color: done ? Colors.grey[100] : Colors.white, fontWeight: FontWeight.bold)),
                  ]),
            )),
            done
                ? AnimatedBuilder(
                    animation: animation,
                    builder: (context, snapshot) {
                      return Column(mainAxisAlignment: MainAxisAlignment.center, children: [
                        Image.asset(
                          "asset/image/kupa.png",
                          width: animation.value,
                        ),
                        Text("Result", style: GoogleFonts.inter(fontSize: 10, color: Colors.white)),
                      ]);
                    })
                : Offstage(),
            isTest
                ? AnimatedBuilder(
                    animation: animation,
                    builder: (context, snapshot) {
                      return Column(mainAxisAlignment: MainAxisAlignment.center, children: [
                        GestureDetector(
                            onTap: () => showDialog(
                                context: context,
                                builder: (BuildContext context) {
                                  return DialogCommon(
                                    warning: false,
                                    title: t("Why Test?"),
                                    descriptions: t("This is your first exercise after at least 3 weeks."),
                                    description2:
                                        t("The first exercise will be a test. The following sets will be recalculated base on your test."),
                                    description3: t("This is the most optimal way for your development"),
                                    text: "OK",
                                    onTap: () => Navigator.of(context).pop(),
                                    onCancel: () => {
                                      Navigator.of(context).pop(),
                                    },
                                  );
                                }),
                            child: Icon(
                              CustomIcon.question_circle,
                              color: Colors.yellowAccent[700],
                              size: 16,
                            )),
                      ]);
                    })
                : Offstage()
          ]),
        ),
      ),
    );
  }

  void skip() {
    showCupertinoDialog(
        useRootNavigator: true,
        context: context,
        builder: (_) => CupertinoAlertDialog(
              title: Text(t("You want to skip really this exercise?")),
              content: Column(children: [
                Divider(),
              ]),
              actions: [
                TextButton(
                    child: Text(t("No")),
                    onPressed: () => {
                          Navigator.pop(context),
                        }),
                TextButton(
                  child: Text(t("Yes")),
                  onPressed: () {
                    Navigator.pop(context);
                    widget.bloc.add(TrainingPlanSkipExercise(detail: widget.detail));
                  },
                )
              ],
            ));
  }
}
