import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { forwardRef, useCallback, useContext, useEffect, useState } from 'react';
import styled from 'styled-components';
import ComboBox from '../ComboBox';
import { useI18n, useTestIds, useUID } from '../../hooks';
import { createUID, withTestIds, createClassName } from '../../utils';
import FormField from '../FormField';
import Flex from '../Flex';
import { defaultThemeProp } from '../../theme';
import PoweredByGoogleImage from './PoweredByGoogleImage';
import CurrentLocationButton from './CurrentLocationButton';
import MapsContext from './MapsContext';
import { getAddress, getCoords, getNavigatorPosition, getPlaceById, getPlacePredictions, isValueACoordinate, loadMapsAPI } from './utils';
import LocationView from './LocationView';
import { StyledLocationView } from './LocationView.styles';
import { getLocationInputTestIds } from './Location.test-ids';
const StyledLocationInput = styled(ComboBox) `
  z-index: 1;
`;
StyledLocationInput.defaultProps = defaultThemeProp;
const StyledLocationMap = styled.div `
  ${StyledLocationView} {
    border-top-left-radius: 0;
    border-top-right-radius: 0;
  }
`;
StyledLocationMap.defaultProps = defaultThemeProp;
const LocationInput = forwardRef(function LocationInput(props, ref) {
    const uid = useUID();
    const { testId, label, labelHidden, id = uid, value = '', info, status, required, readOnly, disabled, additionalInfo, onSelect, onError, onChange, onBlur, bias, defaultToCurrentLocation, onlyCoordinates = false, map, className, ...restProps } = props;
    const testIds = useTestIds(testId, getLocationInputTestIds);
    const { name, ...providerOpts } = useContext(MapsContext);
    const t = useI18n();
    const [placePredictionMenuItems, setPlacePredictionMenuItems] = useState([]);
    const [filterValue, setFilterValue] = useState('');
    const [mapLoading, setMapLoading] = useState(false);
    useEffect(() => {
        (async () => {
            if (defaultToCurrentLocation) {
                setMapLoading(true);
                await loadMapsAPI(name, providerOpts);
                const navigatorPosition = await getNavigatorPosition();
                const currentLocationAddress = await getAddress(navigatorPosition);
                setMapLoading(false);
                onSelect?.(currentLocationAddress);
            }
        })();
    }, []);
    useEffect(() => {
        (async () => {
            try {
                await loadMapsAPI(name, providerOpts);
                if (filterValue) {
                    if (onlyCoordinates) {
                        const { latitude, longitude } = await getCoords(filterValue);
                        setPlacePredictionMenuItems([
                            {
                                primary: t('exact_location'),
                                secondary: [`${latitude}, ${longitude}`],
                                id: createUID(),
                                onClick: () => {
                                    setFilterValue('');
                                    onSelect?.({ latitude, longitude });
                                }
                            }
                        ]);
                    }
                    else {
                        if (isValueACoordinate(filterValue)) {
                            const { latitude, longitude } = await getCoords(filterValue);
                            const { name: addressName, address } = await getAddress({ latitude, longitude });
                            const menuItems = [
                                {
                                    primary: t('exact_location'),
                                    secondary: [`${latitude}, ${longitude}`],
                                    id: createUID(),
                                    onClick: () => {
                                        setFilterValue('');
                                        onSelect?.({
                                            latitude,
                                            longitude
                                        });
                                    }
                                },
                                {
                                    primary: addressName,
                                    secondary: [address],
                                    id: createUID(),
                                    onClick: () => {
                                        setFilterValue('');
                                        onSelect?.({ name: addressName, address, latitude, longitude });
                                    }
                                }
                            ];
                            setPlacePredictionMenuItems(menuItems);
                            return;
                        }
                        const { placePredictions, token } = await getPlacePredictions(filterValue, bias);
                        if (placePredictions.length === 1) {
                            const exactLocation = await getPlaceById(placePredictions[0].place_id, token);
                            const menuItems = placePredictions.map(item => ({
                                id: item.place_id,
                                primary: item.structured_formatting.main_text,
                                secondary: [item.structured_formatting.secondary_text],
                                onClick: (menuItemId) => {
                                    getPlaceById(menuItemId, token).then(menuItemLocation => {
                                        setFilterValue('');
                                        onSelect?.(menuItemLocation);
                                    });
                                }
                            }));
                            if (exactLocation) {
                                menuItems.push({
                                    primary: t('exact_location'),
                                    secondary: [`${exactLocation.latitude}, ${exactLocation.longitude}`],
                                    id: createUID(),
                                    onClick: () => {
                                        setFilterValue('');
                                        onSelect?.({
                                            latitude: exactLocation.latitude,
                                            longitude: exactLocation.longitude
                                        });
                                    }
                                });
                            }
                            setPlacePredictionMenuItems(menuItems);
                        }
                        else {
                            setPlacePredictionMenuItems(placePredictions.map(item => ({
                                id: item.place_id,
                                primary: item.structured_formatting.main_text,
                                secondary: [item.structured_formatting.secondary_text],
                                onClick: (menuItemId) => {
                                    getPlaceById(menuItemId, token).then(menuItemLocation => {
                                        setFilterValue('');
                                        onSelect?.(menuItemLocation);
                                    });
                                }
                            })));
                        }
                    }
                }
                else {
                    setPlacePredictionMenuItems([]);
                }
            }
            catch (e) {
                setPlacePredictionMenuItems([]);
                onError?.(e);
            }
        })();
    }, [filterValue, bias, onError, onSelect, onlyCoordinates]);
    const onInputChange = useCallback((e) => {
        setFilterValue(e.target.value.trim());
        onChange?.(e.target.value);
    }, [onChange]);
    const onMapClick = useCallback((placeInfo) => {
        if (readOnly)
            return;
        if (onlyCoordinates) {
            const coords = {
                latitude: placeInfo.latitude,
                longitude: placeInfo.longitude
            };
            onSelect?.(coords);
            map?.onClick?.(coords);
        }
        else {
            onSelect?.(placeInfo);
            map?.onClick?.(placeInfo);
        }
    }, [readOnly, onSelect, map?.onClick, onlyCoordinates]);
    const Comp = (_jsxs(_Fragment, { children: [_jsx(StyledLocationInput, { id: id, info: info, "data-testid": testIds.control, placeholder: t('location_input_placeholder'), menu: filterValue
                    ? {
                        items: placePredictionMenuItems.concat([
                            {
                                id: createUID(),
                                primary: t('use_input_value', [filterValue]),
                                onClick: () => {
                                    setFilterValue('');
                                    onSelect?.({ name: filterValue });
                                }
                            }
                        ]),
                        emptyText: t('location_not_found_text'),
                        mode: 'action',
                        footer: !map && (_jsx(Flex, { container: { justify: 'end' }, children: _jsx(PoweredByGoogleImage, {}) }))
                    }
                    : undefined, actions: !disabled &&
                    !readOnly && (_jsx(CurrentLocationButton, { onError: onError, onResolve: resolved => {
                        if (onlyCoordinates) {
                            onSelect?.({ latitude: resolved.latitude, longitude: resolved.longitude });
                        }
                        else {
                            onSelect?.(resolved);
                        }
                    } })), onChange: onInputChange, onBlur: () => {
                    setFilterValue('');
                    onBlur?.(value);
                }, value: value, required: required, disabled: disabled, readOnly: readOnly, status: status, ...restProps, className: createClassName('location-input', className) }), map && (_jsx(StyledLocationMap, { children: _jsx(LocationView, { ...map, pins: map.location ? [{ ...map.location }] : [], onClick: onMapClick, onError: onError, disabled: disabled, loading: mapLoading, centerMapOnChange: true }) }))] }));
    return label ? (_jsx(FormField, { testId: testIds, label: label, labelHidden: labelHidden, id: id, info: info, status: status, ref: ref, required: required, disabled: disabled, additionalInfo: additionalInfo, children: Comp })) : (Comp);
});
export default withTestIds(LocationInput, getLocationInputTestIds);
//# sourceMappingURL=LocationInput.js.map