export function loadGoogleMapsApi(apiKey) {
	if (!apiKey) {
		return Promise.reject(new Error('Missing Google Maps API key.'));
	}

	if (window.google && window.google.maps) {
		return Promise.resolve(window.google.maps);
	}

	if (window.gmdsGoogleMapsPromise) {
		return window.gmdsGoogleMapsPromise;
	}

	window.gmdsGoogleMapsPromise = new Promise((resolve, reject) => {
		const existingScript = document.getElementById('gmds-google-maps-js');

		window.gmdsMapsReady = () => {
			resolve(window.google.maps);
			delete window.gmdsMapsReady;
		};

		window.gm_authFailure = () => {
			reject(new Error('Google Maps rejected this API key for the current site.'));
		};

		if (existingScript) {
			return;
		}

		const script = document.createElement('script');
		script.id = 'gmds-google-maps-js';
		script.src = 'https://maps.googleapis.com/maps/api/js?key=' + encodeURIComponent(apiKey) + '&v=weekly&callback=gmdsMapsReady';
		script.async = true;
		script.defer = true;
		script.onerror = () => reject(new Error('Unable to load the Google Maps JavaScript API.'));

		document.head.appendChild(script);
	});

	return window.gmdsGoogleMapsPromise;
}

export function getGestureHandling(allowMouseWheelScroll, allowTouchOperations) {
	if (!allowTouchOperations) {
		return 'none';
	}

	return allowMouseWheelScroll ? 'auto' : 'cooperative';
}

export async function renderGoogleMap(element, options) {
	const {
		address,
		apiKey,
		zoomLevel,
		allowMouseWheelScroll,
		allowTouchOperations,
	} = options;

	if (!element || !address || !apiKey) {
		return;
	}

	const maps = await loadGoogleMapsApi(apiKey);
	const geocoder = new maps.Geocoder();

	const result = await geocoder.geocode({ address });

	if (!result || !result.results || !result.results.length) {
		throw new Error('Unable to geocode this address.');
	}

	const location = result.results[0].geometry.location;
	const map = new maps.Map(element, {
		center: location,
		zoom: zoomLevel,
		scrollwheel: allowMouseWheelScroll,
		gestureHandling: getGestureHandling(allowMouseWheelScroll, allowTouchOperations),
		mapTypeControl: false,
		streetViewControl: false,
		fullscreenControl: false,
	});

	new maps.Marker({
		position: location,
		map,
	});

	return map;
}
