import React, { FC, memo, useEffect, useState } from 'react';
import {
  Map,
  Placemark,
  GeolocationControl,
  ZoomControl,
  withYMaps,
} from '@pbe/react-yandex-maps';
import { YMapsApi } from '@pbe/react-yandex-maps/typings/util/typing';

import { Coordinate, StringLocation } from '../types';
import { isValidLocation, stringifyLocation } from '../helper';

import { KAZAN_CITY_CENTER, parseLocation } from './helper';

export const MapComponent: FC<{
  ymaps?: YMapsApi;
  selectedLocation: StringLocation | null;
  onMapClick: (props: StringLocation) => void;
}> = memo(
  withYMaps(
    ({ ymaps, selectedLocation, onMapClick }) => {
      const [mapCenter, setMapCenter] =
        useState<Coordinate[]>(KAZAN_CITY_CENTER);

      useEffect(() => {
        if (isValidLocation(selectedLocation)) {
          const location = parseLocation(selectedLocation);
          const { coordinates } = location;
          setMapCenter(coordinates);
        }
      }, [selectedLocation]);

      return (
        <Map
          state={{
            center: mapCenter,
            zoom:
              isValidLocation(selectedLocation) &&
              parseLocation(selectedLocation)?.coordinates
                ? 17
                : 10,
          }}
          width='100%'
          onClick={async (e: ymaps.MapEvent) => {
            try {
              const coordinates = e.get('coords');
              const address = await ymaps.geocode(coordinates).then((res) => {
                const firstGeoObject = res.geoObjects.get(
                  0,
                ) as ymaps.GeocodeResult;
                return firstGeoObject.getAddressLine();
              });
              onMapClick(stringifyLocation({ coordinates, address }));
              setMapCenter(coordinates);
            } catch (error) {
              console.error(error);
            }
          }}
        >
          <GeolocationControl options={{ float: 'left' }} />
          <ZoomControl />
          {selectedLocation && <Placemark geometry={mapCenter} />}
        </Map>
      );
    },
    true,
    ['geocode'],
  ),
);
