import 'dart:async';
import 'dart:convert';
import 'dart:math' as math;
import 'dart:math' show cos;
import 'package:SEFER/constant/table_names.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:google_polyline_algorithm/google_polyline_algorithm.dart';
import 'package:SEFER/constant/style.dart';
import 'package:SEFER/views/widgets/elevated_btn.dart';
import 'package:url_launcher/url_launcher.dart';

import '../../../constant/api_key.dart';
import '../../../constant/box_name.dart';
import '../../../constant/colors.dart';
import '../../../constant/links.dart';
import '../../../main.dart';
import '../../../views/Rate/rate_passenger.dart';
import '../../../views/home/Captin/home_captain/home_captin.dart';
import '../../firebase/firbase_messge.dart';
import '../../functions/crud.dart';
import '../../functions/location_controller.dart';

class MapDriverController extends GetxController {
  bool isLoading = true;
  final formKey1 = GlobalKey<FormState>();
  final sosEmergincyNumberCotroller = TextEditingController();
  List data = [];
  List dataDestination = [];
  LatLngBounds? boundsData;
  BitmapDescriptor carIcon = BitmapDescriptor.defaultMarker;
  BitmapDescriptor passengerIcon = BitmapDescriptor.defaultMarker;
  BitmapDescriptor startIcon = BitmapDescriptor.defaultMarker;
  BitmapDescriptor endIcon = BitmapDescriptor.defaultMarker;
  final List<LatLng> polylineCoordinates = [];
  final List<LatLng> polylineCoordinatesDestination = [];
  List<Polyline> polyLines = [];
  List<Polyline> polyLinesDestination = [];
  Set<Marker> markers = {};
  late String passengerLocation;
  late String passengerDestination;
  late String step0;
  late String step1;
  late String step2;
  late String step3;
  late String step4;
  late String passengerWalletBurc;
  late String timeOfOrder;
  late String duration;
  late String totalCost;
  late String distance;
  late String passengerName;
  late String passengerEmail;
  late String totalPassenger;
  late String passengerPhone;
  late String rideId;
  late String isHaveSteps;
  late String paymentAmount;
  late String paymentMethod;
  late String passengerId;
  late String driverId;
  late String tokenPassenger;
  late String durationToPassenger;
  late String walletChecked;
  late String direction;
  late String durationOfRideValue;
  late String status;
  int timeWaitingPassenger = 5; //5 miniute
  bool isPassengerInfoWindow = false;
  bool isBtnRideBegin = false;
  bool isArrivedSend = true;
  bool isdriverWaitTimeEnd = false;
  bool isRideFinished = false;
  bool isRideStarted = false;
  bool isPriceWindow = false;
  double passengerInfoWindow = Get.height * .39;
  double driverEndPage = 100;
  double progress = 0;
  double progressToPassenger = 0;
  double progressInPassengerLocationFromDriver = 0;
  bool isRideBegin = false;
  int progressTimerToShowPassengerInfoWindowFromDriver = 25;
  int remainingTimeToShowPassengerInfoWindowFromDriver = 25;
  int remainingTimeToPassenger = 60;
  int remainingTimeInPassengerLocatioWait = 60;
  bool isDriverNearPassengerStart = false;
  GoogleMapController? mapController;
  late LatLng myLocation;
  int remainingTimeTimerRideBegin = 60;
  String stringRemainingTimeRideBegin = '';
  double progressTimerRideBegin = 0;
  late Timer timer;
  String? mapAPIKEY;
  final zones = <Zone>[];
  String canelString = 'yet';
  late LatLng latLngpassengerLocation;
  late LatLng latLngPassengerDestination;

  void onMapCreated(GoogleMapController controller) async {
    myLocation = Get.find<LocationController>().location as LatLng;
    myLocation = myLocation;
    mapController = controller;
    controller.getVisibleRegion();
    controller.animateCamera(
      CameraUpdate.newLatLng(myLocation),
    );
    update();

    // Set up a timer or interval to trigger the marker update every 3 seconds.
    timer = Timer.periodic(const Duration(seconds: 2), (_) {
      updateMarker();
    });
  }

  void changeStatusDriver() {
    status = 'On';
    update();
  }

  void changeDriverEndPage() {
    remainingTimeTimerRideBegin < 60 ? driverEndPage = 160 : 100;
    update();
  }

  takeSnapMap() {
    mapController!.takeSnapshot();
  }

  @override
  void dispose() {
    mapController!.dispose();
    super.dispose();
  }

  void openGoogleMapFromDriverToPassenger() async {
    var endLat = latLngpassengerLocation.latitude;
    var endLng = latLngpassengerLocation.longitude;

    var startLat = Get.find<LocationController>().myLocation.latitude;
    var startLng = Get.find<LocationController>().myLocation.longitude;

    String url =
        'https://www.google.com/maps/dir/$startLat,$startLng/$endLat,$endLng/&directionsmode=driving';
    if (await canLaunchUrl(Uri.parse(url))) {
      await launchUrl(Uri.parse(url));
    } else {
      throw 'Could not launch google maps';
    }
  }

  void checkIsDriverNearPassenger() async {
    if (isDriverNearPassengerStart) {
      Timer.periodic(const Duration(seconds: 3), (timer) {
        String driverLat =
            Get.find<LocationController>().myLocation.latitude.toString();
        String driverLng =
            Get.find<LocationController>().myLocation.longitude.toString();

        // Replace "passengerLat" and "passengerLng" with the actual passenger's location
        String passengerLat = passengerLocation; // Set the passenger's latitude
        String passengerLng = ""; // Set the passenger's longitude
      });
    }
  }

  void clearPolyline() {
    polyLines = [];
    polyLinesDestination = [];
    polylineCoordinates.clear();
    polylineCoordinatesDestination.clear();
    update();
  }

  void changeRideToBeginToPassenger() {
    isRideBegin = true;
    passengerInfoWindow = Get.height * .22;
    update();
  }

  void startTimerToShowPassengerInfoWindowFromDriver() async {
    // for (int i = 0;
    //     i <= progressTimerToShowPassengerInfoWindowFromDriver;
    //     i++) {
    //   await Future.delayed(const Duration(seconds: 1));
    //   if (canelString != 'Cancel') {
    //     cancelCheckRidefromPassenger();
    //     progress = i / progressTimerToShowPassengerInfoWindowFromDriver;
    //     remainingTimeToShowPassengerInfoWindowFromDriver =
    //         progressTimerToShowPassengerInfoWindowFromDriver - i;

    //     if (remainingTimeToShowPassengerInfoWindowFromDriver == 0) {
    isPassengerInfoWindow = true;
    //   print(isPassengerInfoWindow);
    update();
    startTimerToShowDriverToPassengerDuration();
    // }
    // print(isPassengerInfoWindow);
    // print(remainingTimeToShowPassengerInfoWindowFromDriver);
    // update();
    // } else {
    //   Get.off(HomeCaptain());
    // }
    // }
  }

  String stringRemainingTimeToPassenger = '';
  void startTimerToShowDriverToPassengerDuration() async {
    for (int i = 0; i <= int.parse(durationToPassenger); i++) {
      await Future.delayed(const Duration(seconds: 1));
      progressToPassenger = i / int.parse(durationToPassenger);
      remainingTimeToPassenger = int.parse(durationToPassenger) - i;
      if (remainingTimeToPassenger == 0) {
        isBtnRideBegin = true;
        print(isBtnRideBegin);
        update();
      }
      print(isBtnRideBegin);
      print(remainingTimeToPassenger);

      int minutes = (remainingTimeToPassenger / 60).floor();
      int seconds = remainingTimeToPassenger % 60;
      stringRemainingTimeToPassenger =
          '$minutes:${seconds.toString().padLeft(2, '0')}';

      update();
    }
  }

  String stringRemainingTimeWaitingPassenger = '';

  void startTimerToShowDriverWaitPassengerDuration() async {
    for (int i = 0; i <= timeWaitingPassenger * 60; i++) {
      await Future.delayed(const Duration(seconds: 1));
      progressInPassengerLocationFromDriver = i / (timeWaitingPassenger * 60);
      remainingTimeInPassengerLocatioWait = (timeWaitingPassenger * 60) - i;
      if (isRideBegin == true) {
        remainingTimeInPassengerLocatioWait = 0;
        update();
      }
      if (remainingTimeInPassengerLocatioWait == 0) {
        isdriverWaitTimeEnd = true;
        print(isdriverWaitTimeEnd);
        update();
      }
      print(isdriverWaitTimeEnd);
      print(
          'remainingTimeInPassengerLocatioWait $remainingTimeInPassengerLocatioWait');

      int minutes = (remainingTimeInPassengerLocatioWait / 60).floor();
      int seconds = remainingTimeInPassengerLocatioWait % 60;
      stringRemainingTimeWaitingPassenger =
          '$minutes:${seconds.toString().padLeft(2, '0')}';

      update();
    }
  }

  void driverGoToPassenger() async {
    changeRideToBeginToPassenger();
    await CRUD().post(link: AppLink.updateRides, payload: {
      'id': rideId,
      'driverGoToPassengerTime': DateTime.now().toString(),
      'status': 'Applied'
    });
    FirebaseMessagesController().sendNotificationToAnyWithoutData(
        'DriverIsGoingToPassenger',
        box.read(BoxName.name).toString(),
        tokenPassenger);
    if (box.read(BoxName.googlaMapApp) == true) {
      openGoogleMapFromDriverToPassenger();
    }
  }

  bool isSocialPressed = false;
  driverCallPassenger() async {
    String scam = await getDriverScam();
    if (scam != 'failure') {
      if (int.parse(scam) > 3) {
        box.write(BoxName.statusDriverLocation, 'on');
        Get.find<LocationController>().stopLocationUpdates();
        await CRUD().post(link: AppLink.addNotificationCaptain, payload: {
          'driverID': box.read(BoxName.driverID),
          'title': 'scams operations'.tr,
          'body':
              'you have connect to passengers and let them cancel the order'.tr,
        });
      } else if (isSocialPressed == true) {
        box.write(BoxName.statusDriverLocation, 'off');
        await CRUD().post(link: AppLink.adddriverScam, payload: {
          'driverID': box.read(BoxName.driverID),
          'passengerID': passengerId,
          'rideID': rideId,
          'isDriverCalledPassenger': '$isSocialPressed'
        });
      }
    }
  }

  Future<String> getDriverScam() async {
    var res = await CRUD().post(link: AppLink.getdriverScam, payload: {
      'driverID': box.read(BoxName.driverID),
    });
    if (res == 'failure') {
      print('Scam is failure');
      box.write(BoxName.statusDriverLocation, 'off');
      return '0';
    }
    var d = jsonDecode(res);
    print('Scam is ');
    print(d['message'][0]['count']);
    return d['message'][0]['count'];
  }

  Position? currentPosition;

  calculateDistanceAndTimeSPEEDOMETER() async {
/*  todo 
save to sql
calculate distance and duration 
get from sql 
update ui for totla results 

*/
  }

  void startRideFromDriver() async {
    double _distance =
        await calculateDistanseBetweenDriverAndPassengerLocation();

    if (_distance < 50) {
      changeRideToBeginToPassenger();
      isPassengerInfoWindow = false;
      isRideStarted = true;
      isRideFinished = false;
      remainingTimeInPassengerLocatioWait = 0;
      timeWaitingPassenger = 0;
      box.write(BoxName.statusDriverLocation, 'on');

      update();
      await CRUD().post(link: AppLink.addDriverpayment, payload: {
        'rideId': rideId,
        'amount': paymentAmount,
        'payment_method': paymentMethod,
        'passengerID': passengerId,
        'driverID': box.read(BoxName.driverID).toString(),
      });

      await CRUD().post(link: AppLink.updateRides, payload: {
        'id': rideId,
        'rideTimeStart': DateTime.now().toString(),
        'status': 'Begin',
      });
      FirebaseMessagesController().sendNotificationToAnyWithoutData(
          'RideIsBegin', box.read(BoxName.name).toString(), tokenPassenger);
      rideIsBeginPassengerTimer();
      double pointsSubstraction = 0;
      pointsSubstraction = double.parse(paymentAmount) * -17;
      var res =
          await CRUD().post(link: AppLink.addDriversWalletPoints, payload: {
        'paymentID': 'rideId$rideId',
        'amount': (pointsSubstraction).toString(),
        'paymentMethod': paymentMethod,
        'driverID': box.read(BoxName.driverID).toString(),
      });
      var d = jsonDecode(res);

      update();
      // Start updating location and moving camera
      // updateLocation();
    } else {
      Get.defaultDialog(
        barrierDismissible: false,
        title: 'Your are far from passenger location'.tr,
        middleText:
            'go to your passenger location before\nPassenger cancel trip'.tr,
        confirm: MyElevatedButton(
            title: 'Ok',
            onPressed: () {
              Get.back();
            }),
      );
    }
  }

  calcualateDistsanceInMetet(LatLng prev, LatLng current) async {
    double distance2 = Geolocator.distanceBetween(
      prev.latitude,
      prev.longitude,
      current.latitude,
      current.longitude,
    );
    return distance2;
  }

  double speedoMeter = 0;
  void updateLocation() async {
    StreamSubscription<Position>? locationSubscription;

    try {
      LatLng? latestPosition; // Initialize outside the loop
      for (var i = 0; i < remainingTimeTimerRideBegin; i++) {
        await Future.delayed(const Duration(seconds: 2));
        locationSubscription =
            Geolocator.getPositionStream().listen((Position position) {
          latestPosition = position as LatLng?; // Update latest position

          // Calculate distance using the latest position
          double distance = calcualateDistsanceInMetet(
              currentPosition as LatLng, latestPosition!);
          speedoMeter = distance + speedoMeter;
          print('distance is $distance');
          print('SpedoMeter is $speedoMeter');
          currentPosition = position;
          // Update camera position on the map
          mapController!.animateCamera(
            CameraUpdate.newCameraPosition(
              CameraPosition(
                target: myLocation,
                zoom: 17, // Adjust zoom level as needed
              ),
            ),
          );
        });
        update();
      }

      // Stop listening after ride finishes
      if (!isRideBegin) {
        locationSubscription?.cancel();
      }
    } catch (error) {
      debugPrint('Error listening to GPS: $error');
      // Handle GPS errors gracefully
    }

    // Periodically call updateLocation again
    await Future.delayed(const Duration(seconds: 2));
    updateLocation();
  }

  calculateDistanseBetweenDriverAndPassengerLocation() {
    double distance2 = Geolocator.distanceBetween(
      latLngpassengerLocation.latitude,
      latLngpassengerLocation.longitude,
      Get.find<LocationController>().myLocation.latitude,
      Get.find<LocationController>().myLocation.longitude,
    );
    return distance2;
  }

  addWaittingTimeCostFromPassengerToDriverWallet() async {
    double distance2 = calculateDistanseBetweenDriverAndPassengerLocation();

    if (distance2 > 40) {
      Get.defaultDialog(
          title: 'Your are far from passenger location'.tr,
          middleText:
              'go to your passenger location before\nPassenger cancel trip'.tr,
          confirm: MyElevatedButton(
              title: 'Ok',
              onPressed: () {
                Get.back();
              }));
    } else {
      double cost =
          (distanceBetweenDriverAndPassengerWhenConfirm * .08) + (5 * .06);
      var res = await CRUD().post(link: AppLink.addDriverpayment, payload: {
        'rideId': rideId,
        'amount': cost.toString(),
        'payment_method': 'wait-cancel',
        'passengerID': passengerId,
        'driverID': box.read(BoxName.driverID).toString(),
      });
      if (res != 'failure') {
        Get.snackbar(
          'You will get cost of your work for this trip'.tr,
          '${'you gain'.tr} $cost \$${' in your wallet'.tr}',
          backgroundColor: AppColor.deepPurpleAccent,
        );
      }
      await CRUD().post(link: AppLink.addPassengersWallet, payload: {
        'passenger_id': passengerId,
        'balance': (cost * -1).toString()
      });
      box.write(BoxName.statusDriverLocation, 'off');
      Get.offAll(HomeCaptain());
    }
  }

  void finishRideFromDriver() async {
    double distanceToDestination = Geolocator.distanceBetween(
      latLngPassengerDestination.latitude,
      latLngPassengerDestination.longitude,
      Get.find<LocationController>().myLocation.latitude,
      Get.find<LocationController>().myLocation.longitude,
    );
    // if (distanceToDestination < 50) {
    isRideFinished = true;
    isRideStarted = false;
    isPriceWindow = false;

    box.write(BoxName.statusDriverLocation, 'off');
    // changeRideToBeginToPassenger();
    await CRUD().post(link: AppLink.updateRides, payload: {
      'id': rideId,
      'rideTimeFinish': DateTime.now().toString(),
      'status': 'Finished'
    });
    print('walletChecked is   $walletChecked');
    if (walletChecked == 'true') {
      await CRUD().post(link: AppLink.addPassengersWallet, payload: {
        'passenger_id': passengerId,
        'balance': ((-1) * double.parse(paymentAmount)).toString()
      });
    }
    print('passengerWalletBurc bef   ${double.parse(passengerWalletBurc)}');
    if (double.parse(passengerWalletBurc) < 0) {
      await CRUD().post(link: AppLink.addPassengersWallet, payload: {
        'passenger_id': passengerId,
        'balance': ((-1) * double.parse(passengerWalletBurc)).toString()
      });
      print('passengerWalletBurc  aft  ${double.parse(passengerWalletBurc)}');
    }
    Future.delayed(const Duration(milliseconds: 300));
    FirebaseMessagesController().sendNotificationToPassengerToken(
      'Driver Finish Trip',
      'you will pay to Driver'.tr + ' $totalCost \$'.tr,
      tokenPassenger,
      [
        box.read(BoxName.driverID),
        rideId,
        box.read(BoxName.tokenDriver),
      ],
    );

    // } else {
    //   Get.defaultDialog(
    //       title: 'You don\'t arrive destenation yet .'.tr,
    //       middleText: '',
    //       confirm: MyElevatedButton(
    //           title: 'Ok'.tr,
    //           onPressed: () {
    //             Get.back();
    //           }));
    // }
// add wallet from passenger from driver
    Get.to(() => RatePassenger(), arguments: {
      'passengerId': passengerId,
      'rideId': rideId,
    });
    // Get.back();
  }

  void cancelCheckRidefromPassenger() async {
    var res = await CRUD().get(link: AppLink.getOrderCancelStatus, payload: {
      'order_id': rideId,
    }); //.then((value) {
    print('Cancel fetch--------------------');
    var response = jsonDecode(res);
    canelString = response['data']['status'];
    print('cancel is $canelString');
    update();
    if (canelString == 'Cancel') {
      remainingTimeTimerRideBegin = 0;
      remainingTimeToShowPassengerInfoWindowFromDriver = 0;
      remainingTimeToPassenger = 0;
      isRideStarted = false;
      isRideFinished = false;
      isPassengerInfoWindow = false;
      clearPolyline();
      update();
      Get.defaultDialog(
        title: 'Order Cancelled'.tr,
        titleStyle: AppStyle.title,
        middleText: 'Order Cancelled by Passenger'.tr,
        middleTextStyle: AppStyle.title,
        confirm: MyElevatedButton(
          title: 'Ok'.tr,
          onPressed: () {
            Get.offAll(HomeCaptain());
          },
        ),
      );
    }
  }

  void rideIsBeginPassengerTimer() async {
    // print('mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm');
    // print(durationOfRideValue);
    int durationOfRide = int.parse(durationOfRideValue);
    update();
    for (int i = 0; i <= durationOfRide; i++) {
      await Future.delayed(const Duration(seconds: 1));
      progressTimerRideBegin = i / durationOfRide;
      remainingTimeTimerRideBegin = durationOfRide - i;
      remainingTimeTimerRideBegin < 60 ? driverEndPage = 160 : 100;
      if (remainingTimeTimerRideBegin < 120) {
        // to make driver available on last 2 minute in his trip
        box.write(BoxName.statusDriverLocation, 'off');
      }
      int minutes = (remainingTimeTimerRideBegin / 60).floor();
      int seconds = remainingTimeTimerRideBegin % 60;
      stringRemainingTimeRideBegin =
          '$minutes:${seconds.toString().padLeft(2, '0')}';

      update();
    }
  }

  double calculateDistanceBetweenLocations(LatLng start, LatLng end) {
    double startLat = start.latitude * math.pi / 180;
    double startLon = start.longitude * math.pi / 180;
    double endLat = end.latitude * math.pi / 180;
    double endLon = end.longitude * math.pi / 180;

    double dLat = endLat - startLat;
    double dLon = endLon - startLon;

    double a = math.pow(math.sin(dLat / 2), 2) +
        math.cos(startLat) * math.cos(endLat) * math.pow(math.sin(dLon / 2), 2);
    double c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a));
    double distance = 6371000 * c; // Distance in meters

    return distance;
  }

  double calculateAngleBetweenLocations(LatLng start, LatLng end) {
    double startLat = start.latitude * math.pi / 180;
    double startLon = start.longitude * math.pi / 180;
    double endLat = end.latitude * math.pi / 180;
    double endLon = end.longitude * math.pi / 180;

    double dLon = endLon - startLon;

    double y = math.sin(dLon) * cos(endLat);
    double x = cos(startLat) * math.sin(endLat) -
        math.sin(startLat) * cos(endLat) * cos(dLon);

    double angle = math.atan2(y, x);
    double angleDegrees = angle * 180 / math.pi;

    return angleDegrees;
  }

  double recentDistanceToDash = 0;
  double recentAngelToMarker = 0;
  void updateMarker() async {
    // Remove the existing marker with the ID `MyLocation`.
    markers.remove(MarkerId('MyLocation'));

    // Add a new marker with the ID `MyLocation` at the current location of the user.
    LocationController locationController = Get.find<LocationController>();
    myLocation = locationController.myLocation;
    final previousLocationOfDrivers = await sql.getCustomQuery('''SELECT
  *
FROM
  ${TableName.rideLocation}
WHERE
  order_id = $rideId
ORDER BY
  created_at DESC
LIMIT
  1''');
    print(previousLocationOfDrivers);
//get from sql
    if (previousLocationOfDrivers.isNotEmpty) {
      var lat = double.parse(previousLocationOfDrivers[0]['lat']);
      var lng = double.parse(previousLocationOfDrivers[0]['lng']);
      LatLng prev = LatLng(lat, lng);

      recentDistanceToDash =
          calculateDistanceBetweenLocations(prev, myLocation);
      print('recentAngelToMarker $recentAngelToMarker');
      print('recentDistanceToDash $recentDistanceToDash');
    }
    sql.insertData({
      'order_id': rideId,
      'created_at': DateTime.now().microsecondsSinceEpoch.toString(),
      'lat': myLocation.latitude.toString(),
      'lng': myLocation.longitude.toString(),
    }, TableName.rideLocation);

    markers.add(
      Marker(
        markerId: MarkerId('MyLocation'.tr),
        position: locationController.myLocation,
        draggable: true,
        icon: carIcon,
        rotation: locationController.heading,
        // infoWindow: const InfoWindow(
        //   title: 'Time',
        // ),
      ),
    );

    mapController!.animateCamera(
      CameraUpdate.newLatLng(locationController.myLocation),
    );
    update();
  }

  void addCustomCarIcon() {
    ImageConfiguration config = ImageConfiguration(
        size: const Size(30, 30), devicePixelRatio: Get.pixelRatio
        // scale: 1.0,
        );
    BitmapDescriptor.fromAssetImage(config, 'assets/images/car.png',
            mipmaps: false)
        .then((value) {
      carIcon = value;
      update();
    });
  }

  void addCustomStartIcon() async {
// Create the marker with the resized image

    ImageConfiguration config = ImageConfiguration(
        size: const Size(30, 30), devicePixelRatio: Get.pixelRatio);
    BitmapDescriptor.fromAssetImage(config, 'assets/images/A.png',
            mipmaps: false)
        .then((value) {
      startIcon = value;
      update();
    });
  }

  void addCustomEndIcon() {
    ImageConfiguration config = ImageConfiguration(
        size: const Size(25, 25), devicePixelRatio: Get.pixelRatio);
    BitmapDescriptor.fromAssetImage(config, 'assets/images/b.png',
            mipmaps: false)
        .then((value) {
      endIcon = value;
      update();
    });
  }

  void addCustomPassengerIcon() {
    ImageConfiguration config = ImageConfiguration(
        size: const Size(30, 30), devicePixelRatio: Get.pixelRatio
        // scale: 1.0,
        );
    BitmapDescriptor.fromAssetImage(config, 'assets/images/picker.png',
            mipmaps: false)
        .then((value) {
      passengerIcon = value;
      update();
    });
  }

  double distanceBetweenDriverAndPassengerWhenConfirm = 0;
  getMap(String origin, destination) async {
    isLoading = false;

    update();

    var url =
        ('${AppLink.googleMapsLink}directions/json?&language=${box.read(BoxName.lang)}&avoid=tolls|ferries&destination=$destination&origin=$origin&key=${AK.mapAPIKEY}');

    var response = await CRUD().getGoogleApi(link: url, payload: {});
    data = response['routes'][0]['legs'];
    print(data);
    distanceBetweenDriverAndPassengerWhenConfirm =
        (data[0]['distance']['value']) / 1000;
    final points =
        decodePolyline(response["routes"][0]["overview_polyline"]["points"]);
    for (int i = 0; i < points.length; i++) {
      double lat = points[i][0].toDouble();
      double lng = points[i][1].toDouble();
      polylineCoordinates.add(LatLng(lat, lng));
    }
    if (polyLines.isNotEmpty) {
      clearPolyline();
      var polyline = Polyline(
        polylineId: PolylineId(response["routes"][0]["summary"]),
        points: polylineCoordinates,
        width: 10,
        color: AppColor.blueColor,
      );
      polyLines.add(polyline);
      // rideConfirm = false;
      update();
    } else {
      var polyline = Polyline(
        polylineId: PolylineId(response["routes"][0]["summary"]),
        points: polylineCoordinates,
        width: 10,
        color: AppColor.blueColor,
      );
      // final dataBounds = response["routes"][0]["bounds"];

      // updateCameraFromBoundsAfterGetMap(dataBounds);

// Fit the camera to the bounds

      polyLines.add(polyline);
      // rideConfirm = false;
      //  Define the northeast and southwest coordinates
      final bounds = response["routes"][0]["bounds"];
      LatLng northeast =
          LatLng(bounds['northeast']['lat'], bounds['northeast']['lng']);
      LatLng southwest =
          LatLng(bounds['southwest']['lat'], bounds['southwest']['lng']);

// Create the LatLngBounds object
      LatLngBounds boundsData =
          LatLngBounds(northeast: northeast, southwest: southwest);

// Fit the camera to the bounds
      var cameraUpdate = CameraUpdate.newLatLngBounds(boundsData, 140);
      mapController!.animateCamera(cameraUpdate);
      update();
    }
  }

  getMapDestination(String origin, destination) async {
    var url =
        ('${AppLink.googleMapsLink}directions/json?&language=${box.read(BoxName.lang)}&avoid=tolls|ferries&destination=$destination&origin=$origin&key=${AK.mapAPIKEY}');

    var response = await CRUD().getGoogleApi(link: url, payload: {});
    dataDestination = response['routes'][0]['legs'];
    // print(data);
    final points =
        decodePolyline(response["routes"][0]["overview_polyline"]["points"]);
    for (int i = 0; i < points.length; i++) {
      double lat = points[i][0].toDouble();
      double lng = points[i][1].toDouble();
      polylineCoordinatesDestination.add(LatLng(lat, lng));
    }
    if (polyLinesDestination.isNotEmpty) {
      // clearPolyline();
      var polyline = Polyline(
        polylineId: PolylineId(response["routes"][0]["summary"]),
        points: polylineCoordinatesDestination,
        width: 10,
        color: AppColor.redColor,
      );
      polyLinesDestination.add(polyline);
      // rideConfirm = false;
      update();
    } else {
      var polyline = Polyline(
        polylineId: PolylineId(response["routes"][0]["summary"]),
        points: polylineCoordinatesDestination,
        width: 10,
        color: AppColor.redColor,
      );
      // final dataBounds = response["routes"][0]["bounds"];

      // updateCameraFromBoundsAfterGetMap(dataBounds);
      // polyLinesDestination.add(polyline);
      // rideConfirm = false;
      //  Define the northeast and southwest coordinates

      update();
    }
  }

  void updateCameraFromBoundsAfterGetMap(dynamic response) {
    final bounds = response["routes"][0]["bounds"];
    LatLng northeast =
        LatLng(bounds['northeast']['lat'], bounds['northeast']['lng']);
    LatLng southwest =
        LatLng(bounds['southwest']['lat'], bounds['southwest']['lng']);

// Create the LatLngBounds object
    LatLngBounds boundsData =
        LatLngBounds(northeast: northeast, southwest: southwest);

// Fit the camera to the bounds
    var cameraUpdate = CameraUpdate.newLatLngBounds(boundsData, 140);
    mapController!.animateCamera(cameraUpdate);
  }

  void changePassengerInfoWindow() {
    isPassengerInfoWindow = !isPassengerInfoWindow;
    passengerInfoWindow = isPassengerInfoWindow == true ? 200 : 0;
    update();
  }

  late Duration durationToAdd;
  int hours = 0;
  int minutes = 0;
  @override
  void onInit() async {
    mapAPIKEY = await storage.read(key: BoxName.mapAPIKEY);
    // Get the passenger location from the arguments.
    passengerLocation = Get.arguments['passengerLocation'];
    passengerDestination = Get.arguments['passengerDestination'];
    duration = Get.arguments['Duration'];
    totalCost = Get.arguments['totalCost'];
    passengerId = Get.arguments['passengerId'];
    driverId = Get.arguments['driverId'];
    distance = Get.arguments['Distance'];
    passengerName = Get.arguments['name'];
    passengerEmail = Get.arguments['email'];
    totalPassenger = Get.arguments['totalPassenger'];
    passengerPhone = Get.arguments['phone'];
    walletChecked = Get.arguments['WalletChecked'];
    tokenPassenger = Get.arguments['tokenPassenger'];
    direction = Get.arguments['direction'];
    durationToPassenger = Get.arguments['DurationToPassenger'];
    rideId = Get.arguments['rideId'];
    durationOfRideValue = Get.arguments['durationOfRideValue'];
    paymentAmount = Get.arguments['paymentAmount'];
    paymentMethod = Get.arguments['paymentMethod'];
    isHaveSteps = Get.arguments['isHaveSteps'];
    step0 = Get.arguments['step0'];
    step1 = Get.arguments['step1'];
    step2 = Get.arguments['step2'];
    step3 = Get.arguments['step3'];
    step4 = Get.arguments['step4'];
    passengerWalletBurc = Get.arguments['passengerWalletBurc'];
    timeOfOrder = Get.arguments['timeOfOrder'];

    var coords = passengerLocation.split(',');
    var coordDestination = passengerDestination.split(',');

// Parse to double
    double latPassengerLocation = double.parse(coords[0]);
    double lngPassengerLocation = double.parse(coords[1]);
    double latPassengerDestination = double.parse(coordDestination[0]);
    double lngPassengerDestination = double.parse(coordDestination[1]);
    latLngpassengerLocation =
        LatLng(latPassengerLocation, lngPassengerLocation);
    latLngPassengerDestination =
        LatLng(latPassengerDestination, lngPassengerDestination);
    String lat = Get.find<LocationController>().myLocation.latitude.toString();
    String lng = Get.find<LocationController>().myLocation.longitude.toString();
    String origin = '$lat,$lng';
    // Set the origin and destination coordinates for the Google Maps directions request.
    getMap(origin, passengerLocation);
    isHaveSteps == 'haveSteps'
        ? (
            await getMapDestination(step0, step1),
            await getMapDestination(step1, step2),
            await getMapDestination(step2, step3),
            await getMapDestination(step3, step4),
          )
        : await getMapDestination(passengerLocation, passengerDestination);
    addCustomCarIcon();
    addCustomPassengerIcon();
    addCustomStartIcon();
    addCustomEndIcon();
    // updateMarker();
    startTimerToShowPassengerInfoWindowFromDriver();
    durationToAdd = Duration(seconds: int.parse(duration));
    hours = durationToAdd.inHours;
    minutes = (durationToAdd.inMinutes % 60).round();
    // cancelCheckRidefromPassenger();
    // checkIsDriverNearPassenger();
    super.onInit();
  }
}
