import 'dart:async';
import 'dart:developer';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:location/location.dart';
import 'location_controller.dart';


class OrderTrackingPage extends StatefulWidget {
  var lat;
  var lng;
  OrderTrackingPage({
    this.lat,this.lng
  });

  @override
  OrderTrackingPageState createState() => OrderTrackingPageState();
}

class OrderTrackingPageState extends State<OrderTrackingPage> {
  final Completer<GoogleMapController> mapController = Completer();
  PolylinePoints polylinePoints = PolylinePoints();
  double latitude=0;
  double longitude=0;
  LocationData? currentLocation;
  Location _location = Location();
  String _reachTime = '';

  String googleAPiKey ="AIzaSyDJpK9RVhlBejtJu9xSGfneuTN6HOfJgSM";

  Set<Marker> markers = {};
  Map<PolylineId, Polyline> polylines = {};

  LatLng startLocation = const LatLng(17.416806,78.4521704);
  LocationController locationController = Get.put(LocationController());
  double distance = 0.0;

  @override
  void initState() {
    super.initState();
    _getLocation();
    latitude=widget.lat;
    longitude=widget.lng;
    LatLng endLocation =  LatLng(widget.lat,widget.lng);

    ever<LatLng?>(locationController.locationPosition, (value) {
      if (value != null) {
       // log("${value.latitude} ${value.longitude}");
        var latitude = value.latitude;
        var longitude = value.longitude;
        startLocation = LatLng(latitude, longitude);
        getDirections(endLocation);
      }
    });
    getDirections(endLocation); //fetch direction polylines from Google API
  }


  Future<void> _getLocation() async {
    try {
      currentLocation = await _location.getLocation();
    } catch (e) {
      currentLocation = null;
    }

    // Calculate ETA using current location and destination coordinates
    double eta = _calculateETA( startLocation.latitude, startLocation.longitude,latitude, longitude,);
    // Convert ETA to readable format
    String hours = eta.floor().toString();
    String minutes = ((eta - eta.floor()) * 60).round().toString();
    _reachTime = minutes;
  }

// Function to calculate ETA
  double _calculateETA(double currentLat, double currentLng, double destinationLat, double destinationLng) {
    // Algorithm to calculate ETA based on current location, destination coordinates, and traffic conditions
    // You can use any algorithm or API to calculate ETA based on your requirements
    // Here's an example algorithm:
    double distance = _calculateDistance(currentLat, currentLng, destinationLat, destinationLng); // Calculate distance between current location and destination
    double speed = 30.0; // Assuming an average speed of 30 km/h
    double time = distance / speed; // Calculate time in hours
    return time;
  }

// Function to calculate distance between two coordinates
  double _calculateDistance(double lat1, double lng1, double lat2, double lng2) {
    double rad = 0.017453292519943295; // Math.PI / 180
    double cosLat1 = cos(lat1 * rad);
    double cosLat2 = cos(lat2 * rad);
    double sinLat1 = sin(lat1 * rad);
    double sinLat2 = sin(lat2 * rad);
    double cosLng1 = cos(lng1 * rad);
    double cosLng2 = cos(lng2 * rad);
    double sinLng1 = sin(lng1 * rad);
    double sinLng2 = sin(lng2 * rad);
    double c = cosLat1 * cosLat2 * cosLng2 * sinLng1 + cosLat1 * cosLat2 * sinLng2 * cosLng1 + sinLat1 * sinLat2;
    double distance = 6371 * acos(c); // 6371 is the radius of the Earth in kilometers
    return distance;
  }


  getDirections(endLocation) async {
    markers.clear();

    markers.add(Marker(
      markerId: MarkerId(startLocation.toString()),
      position: startLocation,
      infoWindow: const InfoWindow(
        title: 'Starting Point ',
        snippet: 'Start Marker',
      ),
      icon: locationController.pickupMarker ?? BitmapDescriptor.defaultMarker,
    ));

    markers.add(Marker(
      markerId: MarkerId(endLocation.toString()),
      position: endLocation, //position of marker
      infoWindow: const InfoWindow(
        title: 'Destination Point ',
        snippet: 'Destination Marker',
      ),
      icon: locationController.dropMarker ?? BitmapDescriptor.defaultMarker,
    ));

    List<LatLng> polylineCoordinates = [];

    PolylineResult result = await polylinePoints.getRouteBetweenCoordinates(
      googleAPiKey,
      PointLatLng(startLocation.latitude, startLocation.longitude),
      PointLatLng(endLocation.latitude, endLocation.longitude),
      travelMode: TravelMode.driving,
    );

    if (result.points.isNotEmpty) {
      for (var point in result.points) {
        polylineCoordinates.add(LatLng(point.latitude, point.longitude));
      }
    } else {
     // log(result.errorMessage ?? "Something went wrong");
    }

//polulineCoordinates is the List of longitute and latidtude.
    double totalDistance = 0;
    for(var i = 0; i < polylineCoordinates.length-1; i++){
      totalDistance += calculateDistance(
          polylineCoordinates[i].latitude,
          polylineCoordinates[i].longitude,
          polylineCoordinates[i+1].latitude,
          polylineCoordinates[i+1].longitude);
    }
    print(totalDistance);

    setState(() {
      distance = totalDistance;
    });

    addPolyLine(polylineCoordinates);
  }





  addPolyLine(List<LatLng> polylineCoordinates) async {
    PolylineId id = const PolylineId("poly");
    Polyline polyline = Polyline(
      polylineId: id,
      color: Colors.deepPurpleAccent,
      points: polylineCoordinates,
      width:8,
    );
    polylines[id] =polyline;

    var position = CameraPosition(
        target: LatLng(startLocation.latitude, startLocation.longitude),
        zoom: 18);

    final GoogleMapController controller = await mapController.future;
    controller.animateCamera(CameraUpdate.newCameraPosition(position));

    setState(() {});
  }


  double calculateDistance(lat1, lon1, lat2, lon2){
    var p = 0.017453292519943295;
    var a = 0.5 - cos((lat2 - lat1) * p)/2 +
        cos(lat1 * p) * cos(lat2 * p) *
            (1 - cos((lon2 - lon1) * p))/2;
    return 12742 * asin(sqrt(a));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          GoogleMap(
            //Map widget from google_maps_flutter package
            zoomGesturesEnabled: true,
            //enable Zoom in, out on map
            initialCameraPosition: CameraPosition(
              //innital position in map
              target: startLocation, //initial position
              zoom: 8.0, //initial zoom level
            ),

            markers: markers,
            //markers to show on map
            polylines: Set<Polyline>.of(polylines.values),
            //polylines
            mapType: MapType.normal,
            //map type
            onMapCreated: (controller) {
              //method called when map is created
              if (!mapController.isCompleted) {
                mapController.complete(controller);
              }
            },
          ),

          const SizedBox(
            height: 95,
          ),

          Positioned(
              bottom: 100,
              left: 50,
              child: Container(
                  child: Card(
                    child: Container(
                        padding: EdgeInsets.all(20),
                        child: Text("Total Distance: " + distance.toStringAsFixed(2) + " KM",
                            style: TextStyle(fontSize: 20, fontWeight:FontWeight.bold))
                    ),
                  )
              )),

        /*  Positioned(
              bottom: 150,
              left: 50,
              child: Container(
                  child: Card(
                    child: Container(
                        padding: EdgeInsets.all(20),
                        child: Column(
                          children: [
                            currentLocation != null
                                ? Text('Current location: (${latitude}, ${longitude})')
                                : Text('Location not available'),
                            SizedBox(height: 16),
                            Text('Estimated time of arrival: $_reachTime'),
                          ],
                        )



                    ),
                  )
              )),*/
        ],
      )

    );

  }
}
