/** Lazily loaded Leaflet + OSRM directions workflow. */
export const showLeafletDirections = ( provider, origin, dest, opts = {} ) => {
	if ( ! provider.map || ! origin || ! dest || ! provider.L ) {
		return Promise.resolve( false );
	}
	const url = `https://router.project-osrm.org/route/v1/driving/${ origin.lng },${ origin.lat };${ dest.lng },${ dest.lat }?overview=full&geometries=geojson&steps=true`;
	const fmt = ( meters ) => ( meters >= 1000 ? `${ ( meters / 1000 ).toFixed( 1 ) } km` : `${ Math.round( meters ) } m` );
	return fetch( url )
		.then( ( response ) => response.json() )
		.then( ( data ) => {
			const route = data?.routes?.[ 0 ];
			const geo = route?.geometry;
			if ( ! geo || ! Array.isArray( geo.coordinates ) ) return false;
			const latlngs = geo.coordinates.map( ( [ lng, lat ] ) => [ lat, lng ] );
			provider.clearDirections();
			provider.routeLine = provider.L.polyline( latlngs, { color: '#3858e9', weight: 5, opacity: 0.85 } ).addTo( provider.map );
			provider.map.fitBounds( provider.routeLine.getBounds(), { padding: [ 30, 30 ] } );
			if ( opts.panel ) {
				const dir = ( suffix ) => provider.classFor( `dir__${ suffix }` );
				// Built as nodes with textContent, never as an HTML string: the
				// turn instructions carry road names straight from the routing
				// service, and OpenStreetMap road names are publicly editable.
				// textContent cannot be parsed as markup, so there is nothing to
				// escape and nothing to get wrong later.
				const el = ( tag, className, text ) => {
					const node = document.createElement( tag );
					if ( className ) {
						node.className = className;
					}
					if ( text !== undefined ) {
						node.textContent = text;
					}
					return node;
				};
				const minutes = Math.round( ( route.duration || 0 ) / 60 );
				const list = el( 'ol', dir( 'steps' ) );
				( route.legs?.[ 0 ]?.steps || [] ).forEach( ( step, index ) => {
					const turn = ( step.maneuver?.modifier || step.maneuver?.type || 'continue' ).replace( /_/g, ' ' );
					const road = step.name ? ` onto ${ step.name }` : '';
					const item = document.createElement( 'li' );
					item.appendChild( el( 'span', dir( 'n' ), String( index + 1 ) ) );
					item.appendChild( el( 'span', dir( 't' ), `${ turn }${ road }` ) );
					item.appendChild( el( 'span', dir( 'd' ), fmt( step.distance || 0 ) ) );
					list.appendChild( item );
				} );
				opts.panel.textContent = '';
				opts.panel.appendChild(
					el( 'div', dir( 'sum' ), `${ fmt( route.distance || 0 ) } · ${ minutes } min` )
				);
				opts.panel.appendChild( list );
			}
			return { distance: fmt( route.distance || 0 ), duration: `${ Math.round( ( route.duration || 0 ) / 60 ) } min`, origin: '' };
		} )
		.catch( () => false );
};
