import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:farm_tpf/custom_model/Device.dart';
import 'package:farm_tpf/data/api/app_exception.dart';
import 'package:farm_tpf/data/repository/repository.dart';
import 'package:meta/meta.dart';

part 'device_event.dart';
part 'device_state.dart';

class DeviceBloc extends Bloc<DeviceEvent, DeviceState> {
  final Repository repository;

  DeviceBloc({required this.repository}) : super(DeviceInitial());

  @override
  Stream<DeviceState> mapEventToState(
    DeviceEvent event,
  ) async* {
    if (event is OpenScreen) {
      yield* _mapOpenScreenToState();
    } else if (event is ControlDevice) {
      yield* _mapControlDeviceToState(event.currentDevices, event.updatedDeviceId);
    } else if (event is OnSearch) {
      yield* _mapOnSearchToState(event.query);
    }
  }

  Stream<DeviceState> _mapOnSearchToState(String query) async* {
    yield DisplayDevice.loading();
    try {
      var devices = <Device>[];
      final response = await repository.getDevices(query);
      devices = response;
      devices.sort((a, b) => (a.id ?? -1).compareTo(b.id ?? -1));
      yield DisplayDevice.data(devices);
    } catch (e) {
      yield DisplayDevice.error(AppException.handleError(e));
    }
  }

  Stream<DeviceState> _mapOpenScreenToState() async* {
    yield DisplayDevice.loading();
    try {
      var devices = <Device>[];
      final response = await repository.getDevices("");
      devices = response;
      devices.sort((a, b) => (a.id ?? -1).compareTo(b.id ?? -1));
      yield DisplayDevice.data(devices);
    } catch (e) {
      yield DisplayDevice.error(AppException.handleError(e));
    }
  }

  Stream<DeviceState> _mapControlDeviceToState(List<Device> currentDevices, int updatedDeviceId) async* {
    var devices = <Device>[];
    currentDevices.forEach((device) {
      if (device.id == updatedDeviceId) {
        var updatedStatus = device.status == "1" ? "0" : "1";
        device.status = updatedStatus;
      }
      devices.add(Device.clone(device));
    });
    yield DisplayDevice.data(devices);
  }
}
