import { ControlPosition, useMap } from "react-map-gl/mapbox";
import MapboxGeocoder, { Result } from "@mapbox/mapbox-gl-geocoder";
import { useEffect, useState } from "react";

// export interface GeocoderObject {
//   id: string;
//   place_name: string;
//   center: number[];
//   place_type: string[];
// }

// interface GeocoderResult {
//   result: GeocoderObject;
// }
interface Props {
  mapboxAccessToken: string;
  position: ControlPosition;
  customEntries?: Result[];
  customTransition?: (objectResult: Result) => void;
  resultFunction?: (objectResult: Result) => void;
}

//const MAPBOX_TOKEN = process.env.REACT_APP_MAPBOX_ACCESS_TOKEN;
// const MAPBOX_TOKEN = import.meta.env.VITE_MAPBOX_ACCESS_TOKEN;

// const geoCoder = new MapboxGeocoder({
//   accessToken: MAPBOX_TOKEN ?? "",
//   flyTo: true,
//   marker: false,
//   zoom: 18
// });

export default function Geocoder(props: Props) {
  const { mapboxAccessToken, position, customEntries, resultFunction, customTransition } = props;
  const [geoCoder, setGeoCoder] = useState<MapboxGeocoder>()
  const { current: map } = useMap();

  const localSearch = (query: string) => {
    const matchesCoords = query.match(
      /^[ ]*(?:Lat: )?(-?\d+\.?\d*)[, ]+(?:Lng: )?(-?\d+\.?\d*)[ ]*$/i
    );
    let matchingResults: Result[] = [];
    if (matchesCoords) {
      const coord1 = Number(matchesCoords[1]);
      const coord2 = Number(matchesCoords[2]);
      const matchingCoords: Result[] = [];

      if (coord1 < -90 || coord1 > 90) {
        // coord1 is longitude
        matchingCoords.push({
          id: "Lat: " + coord2 + " Lng: " + coord1,
          place_name: "Lat: " + coord2 + " Lng: " + coord1,
          center: [coord1, coord2],
          place_type: ["coordinate"]
        } as Result);
      }

      if (coord2 < -90 || coord2 > 90) {
        // coord2 is longitude
        matchingCoords.push({
          id: "Lat: " + coord1 + " Lng: " + coord2,
          place_name: "Lat: " + coord1 + " Lng: " + coord2,
          center: [coord2, coord1],
          place_type: ["coordinate"]
        } as Result);
      }

      if (matchingCoords.length === 0) {
        // else could be either lng, lat or lat, lng
        matchingCoords.push({
          id: "Lat: " + coord2 + " Lng: " + coord1,
          place_name: "Lat: " + coord2 + " Lng: " + coord1,
          center: [coord1, coord2],
          place_type: ["coordinate"]
        } as Result);
        matchingCoords.push({
          id: "Lat: " + coord1 + " Lng: " + coord2,
          place_name: "Lat: " + coord1 + " Lng: " + coord2,
          center: [coord2, coord1],
          place_type: ["coordinate"]
        } as Result);
      }

      matchingResults = matchingResults.concat(matchingCoords);
    }

    customEntries?.forEach(obj => {
      if (obj.place_name.toLowerCase().includes(query.toLowerCase())) {
        matchingResults.push(obj);
      }
    });
    return matchingResults;
  };

  //create the geocoder
  useEffect(()=>{
    const g = new MapboxGeocoder({
      accessToken: mapboxAccessToken,
      localGeocoder: localSearch,
      flyTo: customTransition ? false : true,
      marker: false,
      zoom: 18,
    });

    setGeoCoder(g)
  },[mapboxAccessToken])

  // //set the geocoder options
  // useEffect(() => {
  //   //connects the localSearch function to the geocoder if there are custom entries passed in
  //   if (customEntries) {
  //     //need to determine a new way to handle custom search with updated geocoder
  //     //geoCoder.options.localGeocoder = localSearch;
  //   }
  //   //disables the transition that the geocoder would fire if a custom transition was passed in
  //   if (customTransition) {
  //     geoCoder.setFlyTo(false);
  //   }
  // }, [customEntries, customTransition]); // eslint-disable-line react-hooks/exhaustive-deps

  //attach custom functions to event handlers
  useEffect(() => {
    if(geoCoder){
    //event is fired when the search bar is cleared
    geoCoder.on("clear", () => {});

    //event is fired when starting to load the results
    geoCoder.on("loading", () => {});

    //event is fired when the results come back from a search
    geoCoder.on("results", () => {});

    //event is fired when there is an error
    geoCoder.on("error", () => {});

    //event is fired when an option is selected from the results
    geoCoder.on("result", (res) => {
      if (resultFunction) {
        resultFunction(res.result);
      }
      if (customTransition) {
        customTransition(res.result);
      }
    });
    //once the map ref and access token are set up add the control to the map
    if (map) {
      map.addControl(geoCoder, position);
    }
    }
  }, [map, geoCoder]); // eslint-disable-line react-hooks/exhaustive-deps

  return null;
}
