import { Dispatch, SetStateAction, useEffect } from "react";
import { UseFormClearErrors, UseFormSetValue } from "react-hook-form";
import { Place } from "../../../data/datasource/api/entities/place";
import Map, { Marker, useMap } from "react-map-gl";
import "mapbox-gl/dist/mapbox-gl.css";
import { LoadingSpinner } from "../loading_spinner/loading_spinner";

// Define the props interface for the component
interface props {
  setValue: UseFormSetValue<Place>;
  isLoading: boolean;
  clearErrors: UseFormClearErrors<Place>;
  position: Position | null;
  setPosition: Dispatch<SetStateAction<Position | null>>;
}

// Define the Position interface
export interface Position {
  latitude: number;
  longitude: number;
}

// Component to listen for position changes and update the map and form values
const PositionListener = ({
  setValue,
  position,
  setPosition,
  clearErrors,
}: props) => {
  const mapRef = useMap();

  useEffect(() => {
    if (position && position.latitude !== 0 && position.longitude !== 0) {
      // Update form values with the new position
      setValue("latitude", position.latitude);
      setValue("longitude", position.longitude);
      if (mapRef.current) {
        // Fly to the new position on the map
        mapRef.current.flyTo({
          center: [position.longitude, position.latitude],
          zoom: 17,
        });
      }
      // Clear any errors related to latitude and longitude
      clearErrors("latitude");
      clearErrors("longitude");
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [position]);

  return <div />;
};

// Main MapBox component
export const MapBoxComponent = ({
  setValue,
  isLoading,
  position,
  setPosition,
  clearErrors,
}: props) => {
  const defaultCenter = { lat: 23.687, lng: -102.74 };

  return (
    <div style={{ width: "100%", height: "100%" }}>
      {isLoading && <LoadingSpinner />}
      <Map
        mapboxAccessToken={process.env.REACT_APP_MAP_BOX || ""}
        initialViewState={{
          longitude: defaultCenter.lng,
          latitude: defaultCenter.lat,
          zoom: 7,
        }}
        mapStyle="mapbox://styles/mapbox/streets-v9"
        onClick={(event) => {
          if (event.lngLat) {
            // Update position state when the map is clicked
            setPosition({
              latitude: event.lngLat.lat,
              longitude: event.lngLat.lng,
            });
          }
        }}
      >
        <PositionListener
          setValue={setValue}
          isLoading={isLoading}
          position={position}
          clearErrors={clearErrors}
          setPosition={setPosition}
        />
        {position && (
          <Marker
            longitude={position.longitude}
            latitude={position.latitude}
            color="red"
          />
        )}
      </Map>
    </div>
  );
};
