find_remote_datasource

 avatar
unknown
dart
5 months ago
7.2 kB
2
Indexable
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:geocoding/geocoding.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:url_launcher/url_launcher.dart';

import '../../../../core/errors/exceptions.dart';
import '../../../../core/res/media_res.dart';
import '../../../../core/services/api.dart';
import '../../../../core/utils/constanst.dart';
import '../../../../core/utils/core_utils.dart';
import '../../../../core/utils/headers.dart';

import '../../presentation/widgets/custom_marker.dart';
import '../models/charge_station_model.dart';

abstract class FindRemoteDataSource {
  const FindRemoteDataSource();

  Future<List<ChargerStationModel>> getChargeStations();

  Future<void> openMapsNavigation(List<double> coordinates);

  Future<Set<Marker>> loadMarkers(List<ChargerStationModel> chargerStations);

  Future<List<ChargerStationModel>> getFavoriteChargeStations(String userId);

  // Future<void> postFavoriteChargeStation(List<ChargerStationModel> chargerStations) async {}
}

class FindRemoteDataSourceImpl implements FindRemoteDataSource {
  const FindRemoteDataSourceImpl({required Dio dio, required API api})
      : _dio = dio,
        _api = api;

  final Dio _dio;
  final API _api;

  @override
  Future<List<ChargerStationModel>> getChargeStations() async {
    try {
      final result = await _dio.get(_api.find.chargeStations,
          options: Options(
            headers: ApiHeaders.getHeaders(token: kApiKey).headers,
            validateStatus: (status) {
              return status! < 500;
            },
          ),
          queryParameters: {
            'paginate_limit': 20,
            'paginate_enabled': true,
            'sort_by': 'createdAt',
            'sort_order': 'desc',
          });
      var chargeStations = result.data['result'] as List<dynamic>?;

      debugPrint('data: ${result.data}');

      if (chargeStations == null) {
        throw const ServerException(message: "Result null", statusCode: "500");
      }

      return await Future.wait(chargeStations.map((e) async {
        try {
          if (e['coordinates'] != null && e['coordinates'].length == 2) {
            double latitude = e['coordinates'][1];
            double longitude = e['coordinates'][0];

            List<Placemark> placemarks =
                await placemarkFromCoordinates(latitude, longitude);
            Placemark place = placemarks[0];

            final addressText =
                "${CoreUtils.removeFirstWord(text: place.locality.toString())}, ${CoreUtils.removeFirstWord(text: place.subAdministrativeArea.toString())}";
            e['location'] = addressText;
          }
        } catch (e, s) {
          debugPrintStack(stackTrace: s);
          debugPrint("Error while fetching address: $e");
        }
        return ChargerStationModel.fromMap(e);
      }).toList());
    } on DioException catch (e) {
      throw ServerException(
          message: e.response?.data['message'] ?? e.message,
          statusCode: e.response?.statusCode ?? 500);
    } on ServerException {
      rethrow;
    } catch (e, s) {
      debugPrintStack(stackTrace: s);
      throw ServerException(message: e.toString(), statusCode: 505);
    }
  }

  @override
  Future<void> openMapsNavigation(List<double> coordinates) async {
    try {
      final uri = Uri(scheme: "google.navigation", queryParameters: {
        'q': '${coordinates[1]},${coordinates[0]}',
        'mode': 'd'
      });

      if (await canLaunchUrl(uri)) {
        await launchUrl(uri);
      } else {
        throw const ServerException(
            message: 'Could not launch Google Maps', statusCode: 505);
      }
    } on ServerException {
      rethrow;
    } catch (e, s) {
      debugPrintStack(stackTrace: s);
      throw ServerException(message: e.toString(), statusCode: 505);
    }
  }

  @override
  Future<Set<Marker>> loadMarkers(
      List<ChargerStationModel> chargerStations) async {
    try {
      final markers = <Marker>[];

      for (var chargeStation in chargerStations) {
        // check if the charger in the station is available or full
        final chargeStatus = chargeStation.chargers
                .map((e) => e.chargerStatus)
                .contains('Available')
            ? 'Available'
            : 'Full';
        final customMarker = await getCustomMarker(
          statusCharger: chargeStatus,
          width: 100,
          height: 100,
          icon: chargeStatus == 'Available'
              ? MediaRes.availableMarker
              : MediaRes.availableMarker,
        );

        markers.add(Marker(
          markerId: MarkerId(chargeStation.id),
          position: LatLng(
            chargeStation.coordinates[1],
            chargeStation.coordinates[0],
          ),
          // BitmapDescriptor
          icon: customMarker,
          infoWindow: InfoWindow(title: chargeStation.name),
        ));
      }

      // debugPrint("markers: ${markers[0].icon}");
      for (var marker in markers) {
        debugPrint("marker: ${marker.icon}");
      }
      return markers.toSet();
    } catch (e, s) {
      debugPrintStack(stackTrace: s);
      throw ServerException(message: e.toString(), statusCode: 505);
    }
  }

  @override
  Future<List<ChargerStationModel>> getFavoriteChargeStations(
      String userId) async {
    try {
      final result = await _dio.get(
        "$kParkingBaseUrl/get-user-fav-chargestation/$userId",
      );

      var favoriteChargeStations = result.data['favourite'] as List<dynamic>?;

      debugPrint('data: ${result.data}');

      if (favoriteChargeStations == null) {
        throw const ServerException(message: "Result null", statusCode: "500");
      }

      return await Future.wait(favoriteChargeStations.map((e) async {
        try {
          if (e['coordinates'] != null && e['coordinates'].length == 2) {
            double latitude = e['coordinates'][1];
            double longitude = e['coordinates'][0];

            List<Placemark> placemarks =
                await placemarkFromCoordinates(latitude, longitude);
            Placemark place = placemarks[0];

            final addressText =
                "${CoreUtils.removeFirstWord(text: place.locality.toString())}, ${CoreUtils.removeFirstWord(text: place.subAdministrativeArea.toString())}";
            e['location'] = addressText;
          }
        } catch (e, s) {
          debugPrintStack(stackTrace: s);
          debugPrint("Error while fetching address: $e");
        }
        return ChargerStationModel.fromMap(e);
      }).toList());
    } on DioException catch (e) {
      throw ServerException(
          message: e.response?.data['message'] ?? e.message,
          statusCode: e.response?.statusCode ?? 500);
    } on ServerException {
      rethrow;
    } catch (e, s) {
      debugPrintStack(stackTrace: s);
      throw ServerException(message: e.toString(), statusCode: 505);
    }
  }
  
}
Editor is loading...
Leave a Comment