import 'dart:async'; import 'dart:convert'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong2/latlong.dart'; import '../globals.dart' as globals; import '../object_id_utils.dart'; import '../redux/actions.dart'; import 'app_state.dart'; import 'false_positive_types.dart'; import 'your_location.dart'; class FiresApi { FiresApi() { _dio = Dio(); } late final Dio _dio; Future createUser( AppState state, String mobileToken, String lang) async { final Map params = { 'token': state.firesApiKey, 'mobileToken': mobileToken, 'lang': lang }; final String url = '${state.firesApiUrl}mobile/users'; try { final Response> response = await _dio.post>(url, data: params); if (response.statusCode == 200) { final Map? responseData = response.data; if (responseData == null) { throw Exception('Response data is null'); } final Map data = responseData; final Map dataData = data['data'] as Map; return dataData['userId'] as String; } else { throw Exception('Unexpected error on create user'); } } catch (e) { throw Exception('Error creating user: $e'); } } Future> fetchYourLocations(AppState state) async { final String apiKey = state.firesApiKey; final String mobileToken = state.user.token; final String url = '${state.firesApiUrl}mobile/subscriptions/all/$apiKey/$mobileToken'; try { final Response> response = await _dio.get>(url); if (response.statusCode == 200) { final Map? responseData = response.data; if (responseData == null) { throw Exception('Response data is null'); } final Map data = responseData; final Map dataData = data['data'] as Map; final List dataSubscriptions = dataData['subscriptions'] as List; final List subscribed = []; for (int i = 0; i < dataSubscriptions.length; i++) { final Map el = dataSubscriptions[i] as Map; final Map location = el['location'] as Map; final double lat = (location['lat'] as num).toDouble(); final double lon = (location['lon'] as num).toDouble(); final Map id = el['_id'] as Map; subscribed.add(YourLocation( id: objectIdFromJson(id['_str'] as String), lat: lat, lon: lon, subscribed: true, distance: (el['distance'] as num).toInt())); } return subscribed; } else { throw Exception('Unexpected error fetching your locations'); } } catch (e) { throw Exception('Error fetching locations: $e'); } } Future subscribe(AppState state, YourLocation loc) async { final Map params = { 'token': state.firesApiKey, 'mobileToken': state.user.token, 'id': loc.id.hexString, 'lat': loc.lat, 'lon': loc.lon, 'distance': loc.distance }; final String url = '${state.firesApiUrl}mobile/subscriptions'; try { final Response> response = await _dio.post>(url, data: params); if (response.statusCode == 200) { final Map? responseData = response.data; if (responseData == null) { throw Exception('Response data is null'); } final Map data = responseData; final Map dataData = data['data'] as Map; return dataData['subsId'] as String; } else { throw Exception('Unexpected error on subscribe'); } } catch (e) { throw Exception('Error subscribing: $e'); } } Future unsubscribe(AppState state, String subsId) async { final String apiKey = state.firesApiKey; final String mobileToken = state.user.token; final String url = '${state.firesApiUrl}mobile/subscriptions/$apiKey/$mobileToken/$subsId'; try { final Response response = await _dio.delete(url); if (response.statusCode == 200) { return true; } else { throw Exception('Unexpected error on unsubscribe'); } } catch (e) { throw Exception('Error unsubscribing: $e'); } } Future getFiresInLocation( {required AppState state, required double lat, required double lon, required int distance}) async { final String url = '${state.firesApiUrl}fires-in-full/${state.firesApiKey}/$lat/$lon/$distance'; if (globals.isDevelopment) { debugPrint(url); } try { final Response response = await _dio.get(url); if (response.statusCode == 200) { final Map resultDecoded = response.data as Map; final int numFires = (resultDecoded['real'] as num).toInt(); final List fires = resultDecoded['fires'] as List; final List falsePos = resultDecoded['falsePos'] as List; final List industries = resultDecoded['industries'] as List; if (globals.isDevelopment) { // Could log: fires: ${fires.length} falsePos: ${falsePos.length} industries: ${industries.length} } return UpdateFireMapStatsAction( numFires: numFires, fires: fires, falsePos: falsePos, industries: industries); } else throw Exception('Wrong response trying to get fire data'); } catch (e) { throw Exception('Error getting fires: $e'); } } Future> getMonitoredAreas({required AppState state}) async { final String url = '${state.firesApiUrl}status/subs-public-union/${state.firesApiKey}'; const Color color = Color(0xFF145A32); try { final Response response = await _dio.get(url); if (response.statusCode == 200) { final Map resultDecoded = response.data as Map; final List union = []; final Map dataData = resultDecoded['data'] as Map; final Map unionData = dataData['union'] as Map; final String unionValue = unionData['value'] as String; final Map decodedJson = json.decode(unionValue) as Map; final Map geometry = decodedJson['geometry'] as Map; final List multipolygon = geometry['coordinates'] as List; for (final dynamic polygonDynamic in multipolygon) { final List polygon = polygonDynamic as List; for (final dynamic holeDynamic in polygon) { final List hole = holeDynamic as List; final List points = []; for (final dynamic pointDynamic in hole) { final List point = pointDynamic as List; points.add(LatLng( (point[1] as num).toDouble(), (point[0] as num).toDouble())); } union.add(Polyline(points: points, color: color, strokeWidth: 3.0)); } } return union; } else throw Exception('Wrong response trying to get fire data'); } catch (e) { throw Exception('Error getting monitored areas: $e'); } } Future markFalsePositive(AppState state, String mobileToken, String sealed, FalsePositiveType type) async { final Map params = { 'token': state.firesApiKey, 'mobileToken': mobileToken, 'sealed': sealed, 'type': type.toString().split('.')[1] }; final String url = '${state.firesApiUrl}mobile/falsepositive'; try { final Response response = await _dio.post(url, data: params); if (response.statusCode == 200) { if (globals.isDevelopment) { final Map data = response.data as Map; final Map dataData = data['data'] as Map; debugPrint(dataData['upsert'].toString()); } return true; } else { debugPrint(response.data.toString()); return false; } } catch (e) { debugPrint('Error marking false positive: $e'); return false; } } }