import 'dart:async'; import 'dart:collection'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise_ability.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/repository/exercise_device_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/repository/workout_tree_repository.dart'; import 'package:aitrainer_app/service/logging.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/cupertino.dart'; import 'package:meta/meta.dart'; import 'package:aitrainer_app/library/image_cache.dart' as wt; part 'menu_event.dart'; part 'menu_state.dart'; class MenuBloc extends Bloc with Trans, Logging { final WorkoutTreeRepository menuTreeRepository; final ExerciseRepository exerciseRepository = ExerciseRepository(); ExerciseDeviceRepository exerciseDeviceRepository = ExerciseDeviceRepository(); int parent = 0; WorkoutMenuTree? workoutItem; final List listFilterDevice = []; int missingParent = 0; String? missingTreeName = ""; late BuildContext context; ExerciseAbility? ability; MenuBloc({required this.menuTreeRepository}) : super(MenuInitial()) { parent = 0; } void setContext(BuildContext context) { this.context = context; } @override Stream mapEventToState( MenuEvent event, ) async* { try { if (event is MenuCreate) { yield MenuLoading(); //await menuTreeRepository.createTree(); //menuTreeRepository.getBranch(this.parent); //setMenuInfo(); if (Cache().getDevices() != null) { exerciseDeviceRepository.setDevices(Cache().getDevices()!); } yield MenuReady(); } else if (event is MenuRecreateTree) { yield MenuLoading(); // ie. at language changes menuTreeRepository.createTree(); yield MenuReady(); } else if (event is MenuTreeDown) { yield MenuLoading(); parent = event.parent; workoutItem = event.item; if (workoutItem != null) { setAbility(workoutItem!.nameEnglish); } final LinkedHashMap branch = menuTreeRepository.getBranch(event.parent); await getImages(branch); yield MenuReady(); } else if (event is MenuTreeUp) { yield MenuLoading(); // get parent menus or exercises parent = event.parent; workoutItem = menuTreeRepository.getParentItem(parent); LinkedHashMap branch; if (workoutItem != null) { setAbility(workoutItem!.nameEnglish); branch = menuTreeRepository.getBranch(workoutItem!.parent); await getImages(branch); } yield MenuReady(); } else if (event is MenuTreeJump) { yield MenuLoading(); parent = event.parent; workoutItem = menuTreeRepository.getParentItem(parent); if (workoutItem != null) { setAbility(workoutItem!.nameEnglish); } final LinkedHashMap branch = menuTreeRepository.getBranch(workoutItem!.parent); await getImages(branch); yield MenuReady(); } else if (event is MenuClickExercise) { yield MenuLoading(); // get exercise page yield MenuReady(); } else if (event is MenuFilterExerciseType) { yield MenuLoading(); final int deviceId = event.deviceId; if (selectedDevice(deviceId)) { listFilterDevice.add(deviceId); } else { listFilterDevice.remove(deviceId); } yield MenuReady(); } } on Exception catch (ex) { yield MenuError(message: ex.toString()); } } void setAbility(String name) { switch (name) { case "Muscle Build / Shape Toning": ability = ExerciseAbility.oneRepMax; break; case "Endurance": ability = ExerciseAbility.endurance; break; case "Cardio": ability = ExerciseAbility.running; break; case "Test Center": ability = ExerciseAbility.mini_test_set; break; case "My Body": ability = ExerciseAbility.none; break; } log("Ability: " + ability.toString() + " name: " + name); } Future getImages(LinkedHashMap branch) async { wt.ImageCache().clearImageList(); await putBranchImageToHash(branch); log("downloaded image size in KB: " + wt.ImageCache().downloadSize.toString()); } Future putBranchImageToHash(LinkedHashMap branch) async { await Future.forEach(branch.keys, (key) async { final WorkoutMenuTree? value = branch[key]; if (value != null && !value.imageName.contains("asset")) { await wt.ImageCache().putImageToList(value.id, value.imageName); } }); } String? getImage(int id, String name) { String? imageString; if (name.contains("http")) { imageString = wt.ImageCache().getImageString(id, name); } return imageString; } bool selectedDevice(int deviceId) { return !listFilterDevice.contains(deviceId); } LinkedHashMap getFilteredBranch(int? parent) { if (parent == null) return LinkedHashMap(); LinkedHashMap branch = menuTreeRepository.getBranch(parent); if (!menuTreeRepository.isChild(parent) || ability.toString() == ExerciseAbility.none.toString() || listFilterDevice.isEmpty) { return branch; } LinkedHashMap filtered = LinkedHashMap(); branch.forEach((key, value) { final WorkoutMenuTree elem = value; if (elem.exerciseType != null) { for (int i = 0; i < elem.exerciseType!.devices.length; i++) { if (listFilterDevice.contains(elem.exerciseType!.devices[i])) { filtered[elem.name] = elem; } } } }); return filtered; } }