import {useState, useEffect} from "react"
import {AutocompletePrediction, IDecodedAddress} from "../model"
import {useMaps} from "./maps"

const searchTimer: NodeJS.Timeout | null = null

export const useMapAutoComplete = (decodedAddress?: IDecodedAddress) => {
  const [searchText, setSearchText] = useState("")
  const [predictions, setPredictions] = useState<AutocompletePrediction[]>([])
  const [addressData, setAddressData] = useState<IDecodedAddress>(
    decodedAddress || {
      subLocality: "",
      city: "",
      state: "",
      pinCode: "",
      country: "",
      latitude: 0,
      longitude: 0,
    }
  )
  const {getPlacesPredictions, getCurrentLocationData, reverseGeoCode, geocoding, maps, mapCore} = useMaps()
  const {latitude = 0, longitude = 0} = addressData

  useEffect(() => {
    if (searchText.length >= 3) {
      if (searchTimer) clearTimeout(searchTimer)
      setTimeout(() => getPlacesPredictions(searchText, setPredictions), 50)
    } else {
      setPredictions([])
      if (searchTimer) {
        clearTimeout(searchTimer)
      }
    }
  }, [searchText])

  useEffect(() => {
    try {
      const element = document.getElementById("map") as HTMLElement
      const markerElement = document.getElementById("marker-element") as HTMLElement
      if (maps && mapCore && element && markerElement) {
        const {LatLng, event} = mapCore
        const {Map} = maps
        const mapOptions = {
          zoom: 18,
          minZoom: 18,
          maxZoom: 18,
          panControl: false,
          mapTypeControl: false,
          streetViewControl: false,
          center: new LatLng(latitude, longitude),
          disableDefaultUI: false,
          scrollWheel: true,
          draggable: true,
          zoomControl: false,
          fullscreenControl: false,
        }

        const map = new Map(element, mapOptions)
        // element.appendChild(markerElement)
        const handleMapDrag = async () => {
          const position = map.getCenter()
          if (position) {
            const addressData = await reverseGeoCode(position.lat(), position.lng())
            if (addressData) {
              setAddressData(addressData)
            }
          }
        }

        const dragListener = event.addListener(map, "dragend", handleMapDrag)
        const zoomListener = event.addListener(map, "zoom_changed", handleMapDrag)

        return () => {
          dragListener.remove()
          zoomListener.remove()
        }
      }
    } catch (error) {
      console.error(">>>>>>>>>>>>> Google Map Loading Error: ", error)
    }
  }, [maps, latitude, longitude])

  const fetchCurrentLocation = (onSelect: (locationData: IDecodedAddress | null) => void) => {
    getCurrentLocationData(locationData => {
      onSelect(locationData)
      if (locationData) setAddressData(locationData)
    })
  }

  const onClickPlace = async (
    {place_id, structured_formatting}: AutocompletePrediction,
    onDecoded?: (locationData: IDecodedAddress) => void
  ) => {
    if (place_id && geocoding) {
      const geoCoder = new geocoding.Geocoder()
      const {results} = await geoCoder.geocode({placeId: place_id})
      if (results.length) {
        const {lat, lng} = results[0].geometry.location
        let locationData = await reverseGeoCode(lat(), lng())
        if (locationData) {
          locationData = {...locationData, subLocality: structured_formatting.main_text}
          setAddressData(locationData)
          if (onDecoded) onDecoded(locationData)
        }
      }
    }
  }

  return {
    predictions,
    onClickPlace,
    fetchCurrentLocation,
    onChangeSearch: setSearchText,
    searchText,
    addressData,
  }
}
