import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/analytics/models/range_of_aqi.dart';
import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_type_dropdown.dart';
import 'package:syncrow_web/pages/analytics/params/get_range_of_aqi_param.dart';
import 'package:syncrow_web/pages/analytics/services/range_of_aqi/range_of_aqi_service.dart';

part 'range_of_aqi_event.dart';
part 'range_of_aqi_state.dart';

class RangeOfAqiBloc extends Bloc<RangeOfAqiEvent, RangeOfAqiState> {
  RangeOfAqiBloc(this._rangeOfAqiService) : super(const RangeOfAqiState()) {
    on<LoadRangeOfAqiEvent>(_onLoadRangeOfAqiEvent);
    on<ClearRangeOfAqiEvent>(_onClearRangeOfAqiEvent);
    on<UpdateAqiTypeEvent>(_onUpdateAqiTypeEvent);
  }

  final RangeOfAqiService _rangeOfAqiService;

  Future<void> _onLoadRangeOfAqiEvent(
    LoadRangeOfAqiEvent event,
    Emitter<RangeOfAqiState> emit,
  ) async {
    emit(
      state.copyWith(status: RangeOfAqiStatus.loading),
    );
    try {
      final rangeOfAqi = await _rangeOfAqiService.load(event.param);
      emit(
        state.copyWith(
          status: RangeOfAqiStatus.loaded,
          rangeOfAqi: rangeOfAqi,
          filteredRangeOfAqi: _arrangeChartDataByType(
            rangeOfAqi,
            state.selectedAqiType,
          ),
        ),
      );
    } catch (e) {
      emit(
        state.copyWith(
          status: RangeOfAqiStatus.failure,
          errorMessage: '$e',
        ),
      );
    }
  }

  void _onUpdateAqiTypeEvent(
    UpdateAqiTypeEvent event,
    Emitter<RangeOfAqiState> emit,
  ) {
    emit(
      state.copyWith(
        selectedAqiType: event.aqiType,
        filteredRangeOfAqi: _arrangeChartDataByType(state.rangeOfAqi, event.aqiType),
      ),
    );
  }

  List<RangeOfAqi> _arrangeChartDataByType(
    List<RangeOfAqi> rangeOfAqi,
    AqiType aqiType,
  ) {
    final filteredRangeOfAqi = rangeOfAqi.map(
      (data) => RangeOfAqi(
        date: data.date,
        data: data.data.where((value) => value.type == aqiType.code).toList(),
      ),
    );
    return filteredRangeOfAqi.toList();
  }

  void _onClearRangeOfAqiEvent(
    ClearRangeOfAqiEvent event,
    Emitter<RangeOfAqiState> emit,
  ) {
    emit(RangeOfAqiState(selectedAqiType: state.selectedAqiType));
  }
}
