import { LocationObject } from 'expo-location' ; import { useCallback , useEffect , useMemo , useRef , useState } from 'react' ; import * as Storage from './storage' ; import * as Track from './track' ; const geodist = require ( 'geodist' ) ; /**
 * Calculate the rough distance (in meters) between multiple coordinates.
 */ function getDistanceFromLocations ( locations ) { if ( locations . length < 2 ) { return 0 ; } return locations . map ( location => ( { lat : location . coords . latitude , lon : location . coords . longitude } ) ) . reduce ( ( distance , location , index , all ) => { if ( index === 0 ) { return distance ; } const total = distance + geodist ( all [ index - 1 ] , location , { exact : true , unit : 'meters' } ) ; return total ; } , 0 ) ; } /**
 * An easy-to-use hook that combines all required functionality.
 * It keeps the data in sync as much as possible.
 */ export function useLocationTracking ( ) { const [ isTracking , setIsTracking ] = useState < boolean > ( ) ; const onStartTracking = useCallback ( async ( ) => { await Track . startTracking ( ) ; setIsTracking ( true ) ; } , [ ] ) ; const onStopTracking = useCallback ( async ( ) => { await Track . stopTracking ( ) ; setIsTracking ( false ) ; } , [ ] ) ; const onClearTracking = useCallback ( async ( ) => { if ( isTracking ) { await onStopTracking ( ) ; } await Storage . clearLocations ( ) ; } , [ isTracking ] ) ; useEffect ( ( ) => { Track . isTracking ( ) . then ( setIsTracking ) ; } , [ ] ) ; return { isTracking , startTracking : onStartTracking , stopTracking : onStopTracking , clearTracking : onClearTracking } ; } /**
 * A hook to poll for changes in the storage, updates the UI if locations were added.
 */ export function useLocationData ( interval = 3000 ) { const locations = useRef < LocationObject [ ] > ( [ ] ) ; const [ count , setCount ] = useState ( 0 ) ; const onLocations = useCallback ( ( stored ) => { if ( stored . length !== locations . current . length ) { locations . current = stored ; setCount ( locations . current . length ) ; } } , [ setCount , locations ] ) ; useEffect ( ( ) => { Storage . getLocations ( ) . then ( onLocations ) ; const timerId = window . setInterval ( ( ) => Storage . getLocations ( ) . then ( onLocations ) , interval ) ; return ( ) => window . clearInterval ( timerId ) ; } , [ interval ] ) ; return locations . current ; } /**
 * A hook to calculate the distance, in meters, between the registered locations.
 */ export function useLocationDistance ( locations , precision = 2 ) { return useMemo ( ( ) => { const distance = getDistanceFromLocations ( locations ) ; const factor = Math . pow ( 10 , precision ) ; const rounded = Math . round ( distance * factor ) / factor ; return rounded ; } , [ locations , precision ] ) ; }