public override async Task OnAlertAddedOrUpdatedAsync(XSafeZoneAlert alert)
        {
            // NOTE: Compare the constants in XSafeZoneAlertStates to alert.State in order to detemine what the current state is.
            //       Location data is in the alert.Location object, and at minumum provides Latitude, Longitude, Timestamp.

            //       Certain metadata, like name, email, mobile should always be available, but the program should handle it being absent.
            //       Metadata about the raiser can be found in the alert.Raiser object.
            //       e.g. to get their email address, use:
            //       EmailAddress emailAddress = XSafeZoneAlertRaiserFields.EmailAddress.GetValueOrDefault(alert.Raiser);

            Log.Info($"Added alert/updated with id: {alert.GlobalId}, state: {alert.State}, lat: {alert.Location?.Latitude}, lon: {alert.Location?.Longitude}.");
        }
 public override async Task OnAlertRemovedAsync(XSafeZoneAlert alert)
 {
     Log.Info($"Removed alert with id: {alert.GlobalId}.");
 }
 /// <summary>
 ///     Called when an alert has been resolved or canceled by a responder in SafeZone.
 /// </summary>
 /// <remarks>
 ///     The alert parameter is the state of the alert before it was
 ///     removed from the SafeZone system and will not necessarily have
 ///     its state property set to 'resolved' or 'canceled'.
 /// </remarks>
 /// <param name="alert">An object containing the last known full state of the alert in the SafeZone system.</param>
 public abstract Task OnAlertRemovedAsync(XSafeZoneAlert alert);
 /// <summary>
 ///     Called when an alert has been added or updated in SafeZone.
 ///     A new alert should be added in the target system if one does not already
 ///     exist with the same raiser and alert id combination, otherwise the existing
 ///     alert should be updated with any state and location changes that have occured.
 /// </summary>
 /// <remarks>
 ///     This method will be called for oustanding unresolved alerts when the application first
 ///     starts. It is therefore important that updates in the target system are either idempotent,
 ///     or the appropriate checks are made before hand to ensure the state transition is appropriate.
 /// </remarks>
 /// <param name="alert">An object containing the full state of the alert in the SafeZone system.</param>
 public abstract Task OnAlertAddedOrUpdatedAsync(XSafeZoneAlert alert);