import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise.dart';
import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:aitrainer_app/model/training_plan.dart';
import 'package:aitrainer_app/model/training_result.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/repository/training_plan_repository.dart';
import 'package:aitrainer_app/util/app_language.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:flutter/material.dart';
import 'package:syncfusion_flutter_calendar/calendar.dart';

part 'training_log_event.dart';
part 'training_log_state.dart';

class TrainingLogBloc extends Bloc<TrainingLogEvent, TrainingLogState> {
  final ExerciseRepository exerciseRepository = ExerciseRepository();

  TrainingLogBloc() : super(TrainingLogInitial()) {
    on<TrainingLogLoad>(_onLoad);
    on<TrainingLogDelete>(_onDelete);
    on<TrainingResultEvent>(_onResult);
    on<TrainingLogSearch>(_onSearch);
  }

  final List<TrainingResult> _results = [];
  get results => this._results;

  bool search = false;
  int exerciseTypeIdSearched = 0;

  @override
  Future<void> close() {
    return super.close();
  }

  void _onLoad(TrainingLogLoad event, Emitter<TrainingLogState> emit) async {
    emit(TrainingLogLoading());
    await Cache().setActivityDonePrefs(ActivityDone.isExerciseLogSeen);
    _results.clear();
    _results.addAll(getTrainingResults());
    Track().track(TrackingEvent.exercise_log_open);
    emit(TrainingLogReady());
  }

  void _onDelete(TrainingLogDelete event, Emitter<TrainingLogState> emit) async {
    emit(TrainingLogLoading());
    exerciseRepository.exerciseList!.remove(event.exercise);
    await exerciseRepository.deleteExercise(event.exercise);
    if (Cache().getExercises() != null) {
      Cache().getExercises()!.remove(event.exercise);
    }
    _results.clear();
    _results.addAll(getTrainingResults());
    Track().track(TrackingEvent.exercise_log_delete);
    emit(TrainingLogReady());
  }

  void _onSearch(TrainingLogSearch event, Emitter<TrainingLogState> emit) async {
    emit(TrainingLogLoading());
    exerciseTypeIdSearched = event.exerciseTypeId;
    search = true;
    _results.clear();
    _results.addAll(getTrainingResults());
    emit(TrainingLogReady());
  }

  void _onResult(TrainingResultEvent event, Emitter<TrainingLogState> emit) async {
    emit(TrainingLogLoading());
    Track().track(TrackingEvent.exercise_log_result);
    emit(TrainingLogReady());
  }

  List<TrainingResult> getTrainingResults() {
    exerciseRepository.getExerciseList();
    exerciseRepository.sortByDate();
    final TrainingPlanRepository trainingPlanRepository = TrainingPlanRepository();

    final List<TrainingResult> trainings = <TrainingResult>[];
    if (exerciseRepository.exerciseLogList == null) {
      return trainings;
    }
    bool isEnglish = AppLanguage().appLocal == Locale('en');
    int trainingPlanOrigId = 0;
    exerciseRepository.exerciseLogList!.sort((a, b) {
      return a.dateAdd!.compareTo(b.dateAdd!) > 0 ? 1 : -1;
    });
    exerciseRepository.exerciseLogList!.forEach((exercise) {
      final trainingPlanId = exercise.trainingPlanDetailsId;
      final DateTime startTraining = DateTime(
          exercise.dateAdd!.year, exercise.dateAdd!.month, exercise.dateAdd!.day, exercise.dateAdd!.hour, exercise.dateAdd!.minute - 5, 0);
      final DateTime start = DateTime(
          exercise.dateAdd!.year, exercise.dateAdd!.month, exercise.dateAdd!.day, exercise.dateAdd!.hour, exercise.dateAdd!.minute, 0);
      final DateTime end = exercise.trainingPlanDetailsId == null
          ? DateTime(exercise.dateAdd!.year, exercise.dateAdd!.month, exercise.dateAdd!.day, exercise.dateAdd!.hour,
              exercise.dateAdd!.minute + 2, 0)
          : DateTime(exercise.dateAdd!.year, exercise.dateAdd!.month, exercise.dateAdd!.day, exercise.dateAdd!.hour,
              exercise.dateAdd!.minute + 10, 0);
      if (trainingPlanId != null && trainingPlanId != trainingPlanOrigId) {
        trainingPlanOrigId = trainingPlanId;
        TrainingPlan? plan = trainingPlanRepository.getTrainingPlanById(trainingPlanId);
        final String? trainingName = plan != null
            ? isEnglish
                ? plan.name
                : plan.nameTranslations[AppLanguage().appLocal.toString()]
            : "Training";
        trainings.add(TrainingResult(
          exercise: null,
          eventName: trainingName != null ? trainingName : "",
          from: startTraining,
          to: DateTime(exercise.dateAdd!.year, exercise.dateAdd!.month, exercise.dateAdd!.day, exercise.dateAdd!.hour + 2,
              exercise.dateAdd!.minute, 0),
          background: Colors.orange[800]!,
          color: Colors.white,
          isAllDay: false,
          isTest: false,
          isExercise: false,
          summary: null,
        ));
      }
      final ExerciseType? exerciseType = exerciseRepository.getExerciseTypeById(exercise.exerciseTypeId!);
      final String exerciseName = isEnglish ? exerciseType!.name : exerciseType!.nameTranslation;

      Color background = exercise.trainingPlanDetailsId == null ? Colors.blue : Colors.orange;
      if (exerciseTypeIdSearched == exercise.exerciseTypeId) {
        background = Color(0xffb4f500);
      }

      Color color = Colors.white;
      if (exerciseTypeIdSearched == exercise.exerciseTypeId) {
        color = Colors.black;
      }

      trainings.add(TrainingResult(
        exercise: exercise,
        eventName: exerciseName,
        from: start,
        to: end,
        background: background,
        color: color,
        isAllDay: false,
        isTest: exercise.trainingPlanDetailsId == null ? true : false,
        isExercise: true,
        summary: exercise.summary,
      ));
    });
    trainings.sort((a, b) {
      return a.from.compareTo(b.from) > 0 ? -1 : 1;
    });
    return trainings;
  }
}

class TrainingDataSource extends CalendarDataSource {
  TrainingDataSource(List<TrainingResult> source) {
    appointments = source;
  }

  @override
  DateTime getStartTime(int index) {
    return appointments![index].from;
  }

  @override
  DateTime getEndTime(int index) {
    return appointments![index].to;
  }

  @override
  String getSubject(int index) {
    return appointments![index].eventName;
  }

  @override
  Color getColor(int index) {
    //print("Color ${appointments![index].eventName} - ${appointments![index].background}");
    return appointments![index].background;
  }

  @override
  bool isAllDay(int index) {
    return appointments![index].isAllDay;
  }
}