import 'dart:collection';

import 'package:aitrainer_app/model/exercise.dart';
import 'package:intl/intl.dart';
import 'dart:async';
import 'package:aitrainer_app/bloc/development_diagram/development_diagram_bloc.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/repository/workout_tree_repository.dart';
import 'package:aitrainer_app/util/app_language.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';

part 'body_development_event.dart';
part 'body_development_state.dart';

enum DiagramDateFilterGroup { l3m, fm_lm, l3t, yearly }

class BodyDevelopmentBloc extends Bloc<BodyDevelopmentEvent, BodyDevelopmentState> {
  final WorkoutTreeRepository workoutTreeRepository;
  final ExerciseRepository exerciseRepository = ExerciseRepository();

  List<String> legendsL3t = ['2 trainigs ago', '1 training ago', 'last training'];
  List<String> legendsFmlm = ['First month', '1 month ago', 'last month'];
  List<String> legendsL3m = ['2 months ago', '1 month ago', 'last month'];
  List<String> legends = [];
  List<String> dateGroups = ["", "", ""];
  List<int> radarTicks = [];
  List<String> radarFeatures = [];
  List<List<int>> radarData = [];
  List<List<double>> tempRadarData = [];
  DiagramGroup group = DiagramGroup.sumMass;
  DiagramDateFilterGroup filter = DiagramDateFilterGroup.l3t;

  @override
  BodyDevelopmentBloc({required this.workoutTreeRepository}) : super(BodyDevelopmentInitial()) {
    getData();
    on<BodyDevelopmentChangeDate>(_onDateFilterChange);
    on<BodyDevelopmentChangeGroup>(_onGroupChange);
  }

  List<MaterialColor> defaultGraphColors = [
    Colors.green,
    Colors.blue,
    Colors.red,
    Colors.orange,
  ];

  void resetTempData() {
    this.tempRadarData.clear();
    this.tempRadarData = [
      [0, 0, 0, 0, 0, 0, 0, 0],
      [0, 0, 0, 0, 0, 0, 0, 0],
      [0, 0, 0, 0, 0, 0, 0, 0]
    ];
  }

  void getExerciseData() {
    workoutTreeRepository.sortedTree.clear();
    workoutTreeRepository.sortByMuscleType();
    this.resetTempData();
    int index = 0;
    this.workoutTreeRepository.sortedTree.forEach((name, list) {
      print("name: $name");

      int elementIndex = 0;
      list.forEach((element) {
        exerciseRepository.exerciseList = exerciseRepository.getExercisesByExerciseTypeId(element.exerciseTypeId);
        exerciseRepository.sortByDate();
        int exerciseIndex = 0;
        exerciseRepository.exerciseList!.forEach((exercise) {
          final HashMap<String, dynamic> dateGroup = this.getDateGroup(exercise, elementIndex);
          if (dateGroup['dateGroupIndex'] != -1) {
            double unitQuantity = exercise.unitQuantity == null ? 1 : exercise.unitQuantity!;
            //print("index ${dateGroup['dateGroupIndex']} -- dateGroup: ${dateGroup['dateGroup']} -- value ${exercise.quantity! * unitQuantity}");
            tempRadarData[dateGroup['dateGroupIndex']][index] += (exercise.quantity! * unitQuantity) / (elementIndex + exerciseIndex + 1);
            exerciseIndex++;
          }
        });
        elementIndex++;
      });

      index++;
    });
    print(" temp $tempRadarData");
  }

  HashMap<String, dynamic> getDateGroup(Exercise exercise, int elementIndex) {
    HashMap<String, dynamic> rc = HashMap();
    rc['dateGroupIndex'] = -1;
    if (elementIndex == 0) {
      rc['dateGroupIndex'] = 0;
      rc['dateGroup'] = DateFormat(DateFormat.YEAR_MONTH, AppLanguage().appLocal.toString()).format(exercise.dateAdd!);
      dateGroups[0] = rc['dateGroup'];
      dateGroups[1] =
          DateFormat(DateFormat.YEAR_MONTH, AppLanguage().appLocal.toString()).format(DateTime.now().subtract(Duration(days: 32)));
      dateGroups[2] = DateFormat(DateFormat.YEAR_MONTH, AppLanguage().appLocal.toString()).format(DateTime.now());

      print("DateGroups: ==== $dateGroups");
    } else {
      final String dateGroup = DateFormat(DateFormat.YEAR_MONTH, AppLanguage().appLocal.toString()).format(exercise.dateAdd!);
      if (dateGroup == dateGroups[0]) {
        rc['dateGroup'] = dateGroup;
        rc['dateGroupIndex'] = 0;
      } else if (dateGroup == dateGroups[1]) {
        rc['dateGroup'] = dateGroup;
        rc['dateGroupIndex'] = 1;
      } else if (dateGroup == dateGroups[2]) {
        rc['dateGroup'] = dateGroup;
        rc['dateGroupIndex'] = 2;
      }
    }
    return rc;
  }

  Future<void> getData() async {
    this.getExerciseData();
    radarTicks = [20, 40, 60, 80, 100, 120, 140, 160];
    radarData = [
      [80, 95, 45, 67, 83, 40, 56, 78],
      [82, 90, 56, 77, 82, 40, 50, 87],
      [26, 112, 58, 70, 130, 49, 52, 127],
    ];
    switch (this.filter) {
      case DiagramDateFilterGroup.l3t:
        legends = legendsL3t;
        break;
      case DiagramDateFilterGroup.l3m:
        legends = legendsL3m;
        break;
      case DiagramDateFilterGroup.fm_lm:
        legends = legendsFmlm;
        break;
      case DiagramDateFilterGroup.yearly:
        var date = DateTime.now();

        legends = [
          DateFormat(DateFormat.YEAR, AppLanguage().appLocal.toString()).format(date.subtract(Duration(days: 365 * 2))),
          DateFormat(DateFormat.YEAR, AppLanguage().appLocal.toString()).format(date.subtract(Duration(days: 365))),
          DateFormat(DateFormat.YEAR, AppLanguage().appLocal.toString()).format(date)
        ];
        break;

      default:
        legends = legendsL3t;
    }
  }

  void _onDateFilterChange(BodyDevelopmentChangeDate event, Emitter<BodyDevelopmentState> emit) {
    emit(BodyDevelopmentLoading());
    this.filter = event.filter;
    getData();
    emit(BodyDevelopmentReady());
  }

  void _onGroupChange(BodyDevelopmentChangeGroup event, Emitter<BodyDevelopmentState> emit) {
    emit(BodyDevelopmentLoading());
    this.group = event.group;
    getData();
    emit(BodyDevelopmentReady());
  }
}