// ignore_for_file: use_build_context_synchronously

import 'dart:async';
import 'dart:convert';
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:sfm_app/product/services/api_services.dart';
import 'package:sfm_app/product/utils/device_utils.dart';

import '../product/shared/shared_snack_bar.dart';
import '../product/utils/date_time_utils.dart';
import '../feature/device_log/device_logs_model.dart';
import '../feature/devices/device_model.dart';

import '../product/base/bloc/base_bloc.dart';

class DetailDeviceBloc extends BlocBase {
  APIServices apiServices = APIServices();

  final deviceInfo = StreamController<Device>.broadcast();
  StreamSink<Device> get sinkDeviceInfo => deviceInfo.sink;
  Stream<Device> get streamDeviceInfo => deviceInfo.stream;

  final deviceSensor = StreamController<Map<String, dynamic>>.broadcast();
  StreamSink<Map<String, dynamic>> get sinkDeviceSensor => deviceSensor.sink;
  Stream<Map<String, dynamic>> get streamDeviceSensor => deviceSensor.stream;

  final deviceLocation = StreamController<String>.broadcast();
  StreamSink<String> get sinkDeviceLocation => deviceLocation.sink;
  Stream<String> get streamDeviceLocation => deviceLocation.stream;

  final sensorTemps = StreamController<List<SensorLogs>>.broadcast();
  StreamSink<List<SensorLogs>> get sinkSensorTemps => sensorTemps.sink;
  Stream<List<SensorLogs>> get streamSensorTemps => sensorTemps.stream;

  @override
  void dispose() {}

  void getDeviceDetail(
    BuildContext context,
    String thingID,
    Completer<GoogleMapController> controller,
  ) async {
    try {
      Device device = await apiServices.getDeviceInformation(thingID);
      sinkDeviceInfo.add(device);
      if (device.areaPath != null) {
        String fullLocation = await DeviceUtils.instance
            .getFullDeviceLocation(context, device.areaPath!, "");
        log("Location: $fullLocation");
        sinkDeviceLocation.add(fullLocation);
      }
      Map<String, dynamic> sensorMap = {};
      if (device.status!.sensors != null) {
        sensorMap = DeviceUtils.instance
            .getDeviceSensors(context, device.status!.sensors!);
      } else {
        sensorMap = DeviceUtils.instance.getDeviceSensors(context, []);
      }
      sinkDeviceSensor.add(sensorMap);
      if (device.settings!.latitude! != "" &&
          device.settings!.longitude! != "") {
        final CameraPosition cameraPosition = CameraPosition(
          target: LatLng(
            double.parse(device.settings!.latitude!),
            double.parse(device.settings!.longitude!),
          ),
          zoom: 13,
        );
        final GoogleMapController mapController = await controller.future;
        mapController
            .animateCamera(CameraUpdate.newCameraPosition(cameraPosition));
      }
    } catch (e) {
      if (!context.mounted) return;
      showErrorTopSnackBarCustom(context, e.toString());
    }
  }

  void findLocation(BuildContext context, String areaPath) async {
    String fullLocation =
        await DeviceUtils.instance.getFullDeviceLocation(context, areaPath, "");
    sinkDeviceLocation.add(fullLocation);
  }

  void getNearerSensorValue(BuildContext context,String thingID) async {
    try {
      List<SensorLogs> sensorTemps = [];
      DateTime twoDaysAgo = DateTime.now().subtract(const Duration(days: 2));
      String from = DateTimeUtils.instance.formatDateTimeToString(twoDaysAgo);
      String now = DateTimeUtils.instance.formatDateTimeToString(DateTime.now());
      Map<String, dynamic> params = {
        'thing_id': thingID,
        'from': from,
        'to': now,
        'limit': '100',
        'n': '7',
      };
      DeviceLog devicesListLog = await apiServices.getLogsOfDevice(thingID, params);
      if (devicesListLog.sensors!.isNotEmpty) {
        for (var sensor in devicesListLog.sensors!) {
          sensorTemps.add(sensor);
        }
        sensorTemps = sensorTemps.reversed.toList();
        sinkSensorTemps.add(sensorTemps);
      } else {
        sinkSensorTemps.add([]);
      }
    } catch (e) {
      if (!context.mounted) return;
      showErrorTopSnackBarCustom(
          context, e.toString());
      sinkSensorTemps.add([]);
    }
  }
}
