import 'dart:async';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
import 'package:aitrainer_app/model/model_change.dart';
import 'package:aitrainer_app/model/workout_menu_tree.dart';
import 'package:aitrainer_app/repository/exercise_plan_repository.dart';
import 'package:aitrainer_app/repository/workout_tree_repository.dart';
import 'package:aitrainer_app/util/enums.dart';
import 'package:aitrainer_app/util/track.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';

part 'exercise_plan_event.dart';

part 'exercise_plan_state.dart';

class ExercisePlanBloc extends Bloc<ExercisePlanEvent, ExercisePlanState> {
  final WorkoutTreeRepository menuTreeRepository;
  ExercisePlanRepository exercisePlanRepository = ExercisePlanRepository();
  late int customerId;

  ExercisePlanBloc({required this.menuTreeRepository}) : super(ExercisePlanInitial());

  Future<void> getData() async {
    exercisePlanRepository.setCustomerId(customerId);
    await exercisePlanRepository.getLastExercisePlan();
    await exercisePlanRepository.getExercisePlanDetails();
    menuTreeRepository.sortedTree.clear();
    menuTreeRepository.sortByMuscleType();

    menuTreeRepository.sortedTree.forEach((key, value) {
      print("menutree $key");
      List<WorkoutMenuTree> listWorkoutTree = value;
      listWorkoutTree.forEach((workoutTree) {
        workoutTree.selected = false;
        if (exercisePlanRepository.getExercisePlanDetailSize() > 0) {
          ExercisePlanDetail? planDetail = exercisePlanRepository.getExercisePlanDetailByExerciseId(workoutTree.exerciseTypeId);
          if (planDetail != null && planDetail.change != ModelChange.deleted) {
            workoutTree.selected = true;
          }
        }
      });
    });
  }

  void setExercisePlanRepository(ExercisePlanRepository repo) => exercisePlanRepository = repo;

  @override
  Stream<ExercisePlanState> mapEventToState(ExercisePlanEvent event) async* {
    try {
      if (event is ExercisePlanLoad) {
        if (Cache().userLoggedIn == null || Cache().userLoggedIn!.customerId == null) {
          throw Exception("Please log in");
        }
        yield ExercisePlanLoading();
        customerId = Cache().userLoggedIn!.customerId!;
        await this.getData();
        Track().track(TrackingEvent.my_custom_exercise_plan);
        yield ExercisePlanReady();
      }

      if (event is ExercisePlanUpdateUI) {
        yield ExercisePlanLoading();

        WorkoutMenuTree workoutTree = event.workoutTree;
        exercisePlanRepository.setActualPlanDetailByExerciseType(workoutTree.exerciseType!);
        workoutTree.selected = true;

        yield ExercisePlanReady();
      } else if (event is ExercisePlanAddExercise) {
        yield ExercisePlanLoading();
        ExercisePlanDetail planDetail = event.exercisePlanDetail;
        exercisePlanRepository.actualPlanDetail = planDetail;

        if (exercisePlanRepository.getExercisePlanDetailSize() != 0) {
          await exercisePlanRepository.saveExercisePlan();
        }

        this.menuTreeRepository.sortedTree.forEach((key, value) {
          List<WorkoutMenuTree> listTreeItem = value;
          listTreeItem.forEach((element) {
            if (element.exerciseType!.exerciseTypeId == planDetail.exerciseTypeId) {
              element.selected = true;
            }
          });
        });

        yield ExercisePlanReady();
      } else if (event is ExercisePlanRemoveExercise) {
        yield ExercisePlanLoading();
        ExercisePlanDetail planDetail = event.exercisePlanDetail;
        exercisePlanRepository.removeExerciseTypeFromPlanByExerciseTypeId(planDetail.exerciseTypeId);

        this.menuTreeRepository.sortedTree.forEach((key, value) {
          List<WorkoutMenuTree> listTreeItem = value;
          listTreeItem.forEach((element) {
            if (element.exerciseType!.exerciseTypeId == planDetail.exerciseTypeId) {
              element.selected = false;
            }
          });
        });

        if (exercisePlanRepository.getExercisePlanDetailSize() != 0) {
          exercisePlanRepository.saveExercisePlan();
          Track().track(TrackingEvent.my_custom_exercise_plan_save);
        }

        yield ExercisePlanReady();
      }
    } on Exception catch (e) {
      yield ExercisePlanError(message: e.toString());
    }
  }
}