import 'package:hydrated_bloc/hydrated_bloc.dart';

import '../../../../../api/demo/demo_mode.dart';
import 'grade_averages_event.dart';
import 'grade_averages_state.dart';

class GradeAveragesBloc
    extends HydratedBloc<GradeAveragesEvent, GradeAveragesState> {
  // Seeded with a realistic spread in demo mode (average 2.0); empty otherwise.
  static const List<int> _demoGrades = [1, 2, 2, 2, 3, 2, 1, 3, 2, 2];

  GradeAveragesBloc()
    : super(
        GradeAveragesState(
          gradingSystem: GradeAveragesGradingSystem.middleSchool,
          grades: DemoMode.active ? _demoGrades : const [],
        ),
      ) {
    on<GradingSystemChanged>((event, emit) {
      add(ResetAll());
      emit(
        state.copyWith(
          gradingSystem: event.isMiddleSchool
              ? GradeAveragesGradingSystem.middleSchool
              : GradeAveragesGradingSystem.highSchool,
        ),
      );
    });

    on<ResetAll>((event, emit) {
      emit(state.copyWith(grades: []));
    });

    on<ResetGrade>((event, emit) {
      emit(
        state.copyWith(
          grades: [...state.grades]
            ..removeWhere((grade) => grade == event.grade),
        ),
      );
    });

    on<IncrementGrade>((event, emit) {
      emit(state.copyWith(grades: [...state.grades, event.grade]));
    });

    on<DecrementGrade>((event, emit) {
      emit(
        state.copyWith(grades: List.from(state.grades)..remove(event.grade)),
      );
    });
  }

  double average() => state.grades.isEmpty
      ? 0
      : state.grades.reduce((a, b) => a + b) / state.grades.length;
  bool isMiddleSchool() =>
      state.gradingSystem == GradeAveragesGradingSystem.middleSchool;
  bool canDecrementOrDelete(int grade) => state.grades.contains(grade);
  int countOfGrade(int grade) => state.grades.where((g) => g == grade).length;
  int gradesInGradingSystem() =>
      state.gradingSystem == GradeAveragesGradingSystem.middleSchool ? 6 : 16;
  int getGradeFromIndex(int index) => isMiddleSchool() ? index + 1 : 15 - index;

  @override
  GradeAveragesState? fromJson(Map<String, dynamic> json) =>
      GradeAveragesState.fromJson(json);
  @override
  Map<String, dynamic>? toJson(GradeAveragesState state) => state.toJson();
}
