# react-native-ctp-odp

React Native ODP Components

## Installation

```sh
npm install react-native-ctp-odp
```

## Usage

1. Install the required packages

```sh
npm install react-native-ctp-odp
npm install react-native-webview
```

2. Import JMapView object (and types)

```js
import {
  // types
  MAP_TAP_EVENT_TYPE,
  // Objects
  JMapView,
  Utilities,
} from 'react-native-ctp-odp';
```

3. Add a JMapView

```js
const mapRef = useRef<MAP_VIEW_REFERENCE_TYPE>(null);

<JMapView
    style={{ width: "100%", height: "100%" }}
    ref={mapRef}
    onMapMessage={{
        callbacks...
    }}
/>
```

## JMapView Methods

Map methods can be called by adding a refence to the JMapView object. All of the available methods should be visible and typed through typescript.

```js
const mapRef = useRef < MAP_VIEW_REFERENCE_TYPE > null;
<JMapView ref={mapRef} />;

if (mapRef.current) mapRef.current.clearWayfindingPath();
```

```js
  /**
   * Set map venue. Used for changing the map venue. Map may be unresponsive until the onVenueLoaded callback is triggered
   *
   * @param credentials - Map credentials object
   * @param mapOptions - Map options, including styles, user settings, etc.
   */
  setMapVenue: (
    credentials: MAP_CREDENTIALS_TYPE,
    mapOptions?: MAP_OPTIONS_TYPE
  ) => void;

  /**
   * Center map on current user location
   *
   * @param options.zoom - Optional, set zoom level
   * @param options.rotation - Optional, map orientation in degrees
   * @param options.animationDuration - Optional, set animation duration, in ms
   */
  centerMapOnUser: (options: MAP_CENTER_USER_OPTIONS_TYPE) => void;

  /**
   * Center map on specified location. If you are intending to continually follow the user, see setFollowBlueDot
   *
   * @param options.point - [x, y] or [lat, lng], dependent on format param
   * @param options.format - 'X_Y' or 'LAT_LONG'
   * @param options.zoom - Optional, set zoom level. Defaults to 5
   * @param options.rotation - Optional, map orientation in degrees. Defaults to 0
   * @param options.animationDuration - Optional, set animation duration, in ms. Defaults to 1000ms
   */
  centerMapOnPoint: (options: MAP_CENTER_OPTIONS_TYPE) => void;

  /**
   * Focus map to specific view bounds. Used for zooming to a specific area of the map
   *
   * @param options.topLeft - Location of top left corner of view bounds, [x, y] or [lat, lng], dependent on format param
   * @param options.bottomRight - Location of bottom right corner of view bounds, [x, y] or [lat, lng], dependent on format param
   * @param options.format - 'X_Y' or 'LAT_LONG'. Defaults to 'LAT_LONG'
   * @param options.rotation - Optional, map orientation in degrees. Defaults to 0
   * @param options.animationDuration - Optional, set animation duration, in ms. Defaults to 1000ms
   */
  setMapViewBounds: (options: MAP_ZOOM_BOUNDS_OPTIONS_TYPE) => void;

  /**
   * Focus map to currently displayed path. If you want the map to automatically center on the path, use the shouldFocus parameter on the drawNavigationPath method
   *
   * @param options.margin - Percentage to pad edges of path, 0-1. 0.25 = 12.5% padding on each side
   * @param options.rotation - Optional, map orientation in degrees. Defaults to 0
   * @param options.animationDuration - Optional, set animation duration, in ms. Defaults to 1000ms
   */
  setMapViewToPath: (options: MAP_ZOOM_TO_PATH_OPTIONS_TYPE) => void;

  /**
   * Set the map to follow the user location
   *
   * @param enabled - Percentage to pad edges of path, 0-1
   * @param rotate - Optional, indicate whether to rotate map with user heading. Defaults to false
   * @param interval - Optional, set the update interval, in ms. Defaults to 500ms
   */
  setFollowBlueDot: (
    enabled: boolean,
    rotate?: boolean,
    interval?: number
  ) => void;

  /**
   * Update the position of the user, by lat/long. This is expected to be joined with the ODP onNavigationUpdate method output
   *
   * @param lat - latitude of the user, in degrees
   * @param long - longitude of the user, in degrees
   * @param heading - Current heading of the user, in degrees
   * @param confidence - Confidence of new location, 0-100 (100 is extremely confident). Used to filter the user location
   */
  setUserPosition: (
    lat: number,
    long: number,
    heading: number,
    confidence: number
  ) => void;

  /**
   * Update the position of the user, in map coordinates
   *
   * @param x - x coordinate of user, in map coordinates
   * @param y - y coordinate of user, in map coordinates
   * @param heading - Current heading of the user, in degrees
   * @param confidence - Confidence of new location, 0-100 (100 is extremely confident). Used to filter the user location
   */
  setUserPositionXY: (
    x: number,
    y: number,
    heading: number,
    confidence: number
  ) => void;

  /**
   * Erase all wayfinding paths currently displayed and associated markers
   */
  clearWayfindingPath: () => void;

  /**
   * Generate a navigation path from the user's current location to the specified waypoint. This will trigger the onNavigationPathGenerated callback when complete
   *
   * @param waypointId - Jibestream waypoint ID for destination. Can be retrieved from the onSearchDestinationsGenerated callback
   */
  wayfindToWaypoint: (waypointId: number) => void;

  /**
   * Generate a navigation path between two specified waypoints. This will trigger the onNavigationPathGenerated callback when complete
   *
   * @param originId - Jibestream waypoint ID for origin. Can be retrieved from the onSearchDestinationsGenerated callback
   * @param destinationId - Jibestream waypoint ID for destination. Can be retrieved from the onSearchDestinationsGenerated callback
   */
  wayfindBetweenWaypoints: (originId: number, destinationId: number) => void;

  /**
   * Draw an already generated navigation path, using the path ID from the onNavigationPathGenerated callback
   *
   * @param pathId - Path ID from onNavigationPathGenerated callback
   * @param shouldFocus - If true, map will center on path after path is drawn
   * @param style - Add custom styles to path
   * @param originIcon - Image object for icon to place at path origin
   * @param destinationIcon - Image object for icon to place at path destination
   */
  drawNavigationPath: (
    pathId: string,
    {
      shouldFocus,
      style,
      originIcon,
      destinationIcon,
    }: {
      shouldFocus?: boolean;
      style?: JIBESTREAM_STYLE_TYPE;
      originIcon?: MAP_IMAGE_TYPE;
      destinationIcon?: MAP_IMAGE_TYPE;
    }
  ) => void;

  /**
   * Style all units corresponding to the specified destination
   *
   * @param destinationId - ID of destination
   * @param style - Style to apply to units
   */
  styleUnitsForDestination: (
    destinationId: number,
    style?: JIBESTREAM_STYLE_TYPE
  ) => void;

  /**
   * Add a custom icon to the map
   *
   * @param coordinates - [x, y] or [lat, lng], dependent on format param
   * @param coordType - 'X_Y' or 'LAT_LONG'. Defaults to 'LAT_LONG'
   * @param icon - Icon to place on map
   */
  addMapIcon: (
    coordinates: number[],
    coordType: COORDINATE_TYPE,
    icon: MAP_IMAGE_TYPE
  ) => void;
```

## JMapView Callbacks

Map callback methods are specified through the onMapMessage property.

```js
<JMapView
  onMapMessage={{
    onMapTappedGeneric: (event: MAP_TAP_EVENT) => {
      console.log(event.localPoint);
    },
  }}
/>;

if (mapRef.current) mapRef.current.clearWayfindingPath();
```

```js
  /**
   * Callback method triggered when a navigation path and instructions are generated by the GUI, most likely from the wayfindToWaypoint or wayfindBetweenWaypoints methods
   *
   * @param pathId - The ID of the generated path (originId_destinationId). Used to render path (drawNavigationPath)
   * @param instructions - Array of generated instructions
   * @param start - Start waypoint
   * @param end - End waypoint
   * @param jibestreamPath - Generated path in jibestream format
   * @param path - Generated path in GeoJSON
   */
  onNavigationPathGenerated?: (
    pathId: string,
    instructions: INSTRUCTION_TYPE[],
    start: JIBESTREAM_WAYPOINT_TYPE,
    end: JIBESTREAM_WAYPOINT_TYPE,
    jibestreamPath: JIBESTREAM_PATH_TYPE[],
    path: GEOJSON_PATH_TYPE
  ) => void;

  /**
   * Callback method triggered when the user strays off of the navigation path. This method is only triggered if the autoReroute option is set to true in the mapOptions object
   *
   * @param pathId - The ID of the generated path (originId_destinationId). Used to render path (drawNavigationPath)
   * @param instructions - Array of generated instructions
   * @param start - Start waypoint
   * @param end - End waypoint
   * @param jibestreamPath - Generated path in jibestream format
   * @param path - Generated path in GeoJSON
   */
  onRerouteNavigationPathGenerated?: (
    pathId: string,
    instructions: INSTRUCTION_TYPE[],
    start: JIBESTREAM_WAYPOINT_TYPE,
    end: JIBESTREAM_WAYPOINT_TYPE,
    jibestreamPath: JIBESTREAM_PATH_TYPE[],
    path: GEOJSON_PATH_TYPE
  ) => void;

  /**
   * Callback method triggered when the user position changes
   *
   * @param userPosition - [x, y] of the user in map coordinates
   */
  onUserPositionUpdated?: (userPosition: number[]) => void;

  /**
   * Callback method triggered when the map generates the set of possible destinations, triggered on load an after setMapVenue
   *
   * @param destinations - Array of destinations
   */
  onSearchDestinationsGenerated?: (
    destinations: JIBESTREAM_DESTINATION_TYPE[]
  ) => void;

  /**
   * Callback method triggered when the module encounters an error. Intended for logging only
   *
   * @param msg - Error message, human readable
   */
  onError?: (msg: string) => void;

  /**
   * Callback method triggered when the map venue is fully initialized. The map is now ready to be used
   *
   * @param venueId - ID of the venue which finished initializing
   */
  onVenueLoaded?: (venueId: number) => void;

  /**
   * Callback method triggered when the map is tapped
   *
   * @param event - Location and destination (if available) of tapped location
   */
  onMapTappedGeneric?: (event: MAP_TAP_EVENT_TYPE) => void;

  /**
   * Callback method the user enters or exits a geofence (configured on {@link https://maps.jibestream.com/geofence-manager})
   *
   * @param entered - True if user entered geofence(s), false if user exited geofence(s)
   * @param geofences - Array of geofences the user entered or exited
   */
  onGeofencesChanged?: (
    entered: boolean,
    geofences: JIBESTREAM_GEOFENCE_TYPE[]
  ) => void;

  /**
   * Callback method the path simulator status changes
   *
   * @param status - Status of current path simulation, including state (active/paused), current location, and time remaining
   */
  onSimulationStatusChanged?: (status: SIMULATION_STATUS_TYPE) => void;
```

## JOdpViewModule Methods

The JODPView module can be used to get a users location from the navigation beacons. This module can be initialized as shown below:

```js
const odpRef = useRef < ODP_VIEW_REFERENCE_TYPE > null;
<JOdpViewModule ref={odpRef} />;

if (odpRef.current) odpRef.current.startOdp('key', 'host');
```

```js
  /**
   * Start the ODP solution. Should trigger onReady and onKeyValidation callbacks, then consistent navigation updates
   *
   * @param key - ODP authentication key
   * @param host - IP address of authentication server
   * @param interval - How often the navigation reading should update measured in ms. Defaults to 1000 ms.
   */
  startOdp: (key: string, host: string, interval_ms: number=1000) => void;

  /**
   * Stop ODP positioning updates
   */
  stopOdp: () => void;

  /**
   * Upload ODP logs to Jibestream team for manual review
   */
  uploadLogs: () => void;
```

## JOdpViewModule Callbacks

The JOdpView module can be used to get a users location from the navigation beacons. This module can be subscribed to as shown below:

```js
<JOdpViewModule
  ref={odpRef}
  onOdpEvent={{
    onReady: (event) => console.log('ODP onReady', event),
    onKeyValidation: (event) => console.log('ODP onKeyValidation', event),
    onNavigationUpdate: (event) => console.log('ODP onNavigationUpdate', event),
    onFacilityUpdate: (event) => console.log('ODP onFacilityUpdate', event),
  }}
/>
```

```js
  /**
   * Callback method ODP ready state has changed
   *
   * @param message - Status of ready state
   */
  onReady?: (message: ODP_ON_READY_TYPE) => void;

  /**
   * Callback method ODP key validation has occurred
   *
   * @param message - Status of key validation (if false, host/key is invalid)
   */
  onKeyValidation?: (message: ODP_ON_KEY_VALIDATION_TYPE) => void;

  /**
   * Callback method ODP new location emitted. The user location will not change unless the setUserPosition method is called with the new location
   *
   * @param message - Location object
   */
  onNavigationUpdate?: (message: ODP_ON_NAVIGATION_UPDATE_TYPE) => void;

  /**
   * Callback method ODP user has entered a new facility
   *
   * @param message - Metadata of facility
   */
  onFacilityUpdate?: (message: ODP_ON_FACILITY_UPDATE_TYPE) => void;
```

## Utilities Object

The Utilities object, imported alongside the JMapView, enalbles proessing of instructions.

- preProcessPath(path: JIBESTREAM_PATH_TYPE[], instructions: INSTRUCTION_TYPE[])
  - Add start and end points to instructions from path. This will enable easy generation of current instruction and distance remaining
- getCurrentInstruction(userLocation: number[], instructions: INSTRUCTION_TYPE[])
  - Get current instruction from user location and processed instructions.

4. Implement callbacks and call methods from the map reference!

See [JMapView Methods](#jmapview-methods) and [JMapView Callbacks](#jmapview-callbacks) sections

## Contributing

See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.

## License

MIT

---

Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
