import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:widget_to_marker/widget_to_marker.dart';

import 'package:anyway/constants.dart';
import 'package:anyway/structs/landmark.dart';
import 'package:anyway/structs/trip.dart';
import 'package:anyway/modules/landmark_map_marker.dart';


class CurrentTripMap extends StatefulWidget {
  final Trip? trip;

  const CurrentTripMap({super.key, this.trip});

  @override
  State<CurrentTripMap> createState() => _CurrentTripMapState();
}

class _CurrentTripMapState extends State<CurrentTripMap> {
  late GoogleMapController mapController;

  final CameraPosition _cameraPosition = const CameraPosition(
    target: LatLng(48.8566, 2.3522),
    zoom: 11.0,
  );
  Set<Marker> mapMarkers = <Marker>{};
  Set<Polyline> mapPolylines = <Polyline>{};

  @override
  void initState() {
    super.initState();
    widget.trip?.addListener(setMapMarkers);
    widget.trip?.addListener(setMapRoute);

  }

  @override
  void dispose() {
    widget.trip?.removeListener(setMapMarkers);
    widget.trip?.removeListener(setMapRoute);

    super.dispose();
  }

  void _onMapCreated(GoogleMapController controller) async {
    mapController = controller;
    List<double>? newLocation = widget.trip?.landmarks.firstOrNull?.location;
    if (newLocation != null) {
      CameraUpdate update = CameraUpdate.newLatLng(LatLng(newLocation[0], newLocation[1]));
      controller.moveCamera(update);
    }
    setMapMarkers();
    setMapRoute();
  }

  void _onCameraIdle() {
    // print(mapController.getLatLng(ScreenCoordinate(x: 0, y: 0)));
  }

  void setMapMarkers() async {
    Iterator<(int, Landmark)> it = (widget.trip?.landmarks.toList() ?? []).indexed.iterator;

    while (it.moveNext()) {
      int i = it.current.$1;
      Landmark landmark = it.current.$2;

      MarkerId markerId = MarkerId("${landmark.uuid} - ${landmark.visited}");
      List<double> location = landmark.location;
      // only create a new marker, if there is no marker for this landmark
      if (!mapMarkers.any((Marker marker) => marker.markerId == markerId)) {
        Marker marker = Marker(
          markerId: markerId,
          position: LatLng(location[0], location[1]),
          icon: await ThemedMarker(landmark: landmark, position: i).toBitmapDescriptor(
            logicalSize: const Size(150, 150),
            imageSize: const Size(150, 150),
          )
        );
        setState(() {
          mapMarkers.add(marker);
        });
      }
    }
  }

  void setMapRoute() async {
    List<Landmark> landmarks = widget.trip?.landmarks.toList() ?? [];
    Set<Polyline> polyLines = <Polyline>{};

    if (landmarks.length < 2) {
      return;
    }

    for (Landmark landmark in landmarks) {
      if (landmark.next != null) {
        List<LatLng> step = [
          LatLng(landmark.location[0], landmark.location[1]),
          LatLng(landmark.next!.location[0], landmark.next!.location[1])
        ];
        Polyline stepLine = Polyline(
          polylineId: PolylineId('step-${landmark.uuid}'),
          points: step,
          color: landmark.visited || (landmark.next?.visited ?? false) ? Colors.grey : PRIMARY_COLOR,
          width: 5
        );
        polyLines.add(stepLine);
      }
    }

    setState(() {
      mapPolylines = polyLines;
    });
  }

  @override
  Widget build(BuildContext context) {
    Future<SharedPreferences> preferences = SharedPreferences.getInstance();

    return FutureBuilder(
      future: preferences,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          SharedPreferences prefs = snapshot.data as SharedPreferences;
          bool useLocation = prefs.getBool('useLocation') ?? true;
          return _buildMap(useLocation);
        } else {
          return const CircularProgressIndicator();
        }
      },
    );
  }

  Widget _buildMap(bool useLocation) {
    return GoogleMap(
      onMapCreated: _onMapCreated,
      initialCameraPosition: _cameraPosition,
      onCameraIdle: _onCameraIdle,
      markers: mapMarkers,
      polylines: mapPolylines,
      cloudMapId: MAP_ID,
      mapToolbarEnabled: false,
      zoomControlsEnabled: false,
      myLocationEnabled: useLocation,
      myLocationButtonEnabled: false,
    );
  }
}
