//
// Copyright 2014-2015 Amazon.com,
// Inc. or its affiliates. All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//
using Amazon.Runtime;
using Amazon.Runtime.Internal;
using Amazon.Runtime.Internal.Util;
using Amazon.Util.Internal;
using Amazon.Util.Internal.PlatformServices;
using System;
using System.Collections.Generic;
using System.Threading;
namespace Amazon.CognitoSync.SyncManager
{
public partial class Dataset : IDisposable
{
INetworkReachability _netReachability;
private AsyncOptions OnConnectivityOptions = null;
///
/// Synchronize between local storage and remote storage.
///
/// Amazon Cognito Sync Dev. Guide - Synchronizing Local Data with the Sync Store
public virtual void SynchronizeAsync(AsyncOptions options = null)
{
options = options == null ? new AsyncOptions() : options;
if (_netReachability.NetworkStatus == NetworkStatus.NotReachable)
{
FireSyncFailureEvent(new NetworkException("Network connectivity unavailable."), options);
return;
}
SynchronizeHelperAsync(options);
}
private void DatasetSetupInternal()
{
_netReachability = ServiceFactory.Instance.GetService();
_netReachability.NetworkReachabilityChanged += OnNetworkReachabilityChanged;
}
///
/// Attempt to synchronize when connectivity is available. If
/// the connectivity is available right away, it behaves the same as
/// . Otherwise it listens to connectivity
/// changes, and will do a sync once the connectivity is back. Note that if
/// this method is called multiple times, only the last synchronize request
/// is kept. If either the dataset or the callback is garbage collected
/// , this method will not perform a sync and the callback won't fire.
///
public virtual void SynchronizeOnConnectivity(AsyncOptions options = null)
{
if (_netReachability.NetworkStatus != NetworkStatus.NotReachable)
{
SynchronizeAsync(options);
}
else
{
waitingForConnectivity = true;
OnConnectivityOptions = options;
}
}
private void OnNetworkReachabilityChanged(object sender, NetworkStatusEventArgs e)
{
if (!waitingForConnectivity)
{
return;
}
if (e.Status != NetworkStatus.NotReachable)
{
var options = OnConnectivityOptions;
OnConnectivityOptions = null;
SynchronizeAsync(options);
}
}
///
/// Releases the resources consumed by this object if disposing is true.
///
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
ClearAllDelegates();
_netReachability.NetworkReachabilityChanged -= OnNetworkReachabilityChanged;
_disposed = true;
}
}
private void SynchronizeHelperAsync(AsyncOptions options)
{
try
{
if (locked)
{
_logger.InfoFormat("Already in a Synchronize. Queueing new request.", DatasetName);
queuedSync = true;
return;
}
else
{
locked = true;
}
waitingForConnectivity = false;
InternalSDKUtils.AsyncExecutor(() =>
{
//make sure we have the updated credentials;
SynchornizeInternal(options);
}, new AsyncOptions() { ExecuteCallbackOnMainThread = false });
}
catch (Exception e)
{
FireSyncFailureEvent(e, options);
_logger.Error(e, "");
}
}
///
/// Fires a Sync Success Event
///
/// List of records after successful sync
/// AsyncOptions object that controls whether
protected void FireSyncSuccessEvent(List records, AsyncOptions options)
{
if (options.ExecuteCallbackOnMainThread)
{
// Enqueue the callback so that the Unity main thread dispatcher
// can invoke the callback on the main thread.
UnityRequestQueue.Instance.ExecuteOnMainThread(() =>
{
FireSyncSuccessEvent(records);
});
}
else
{
FireSyncSuccessEvent(records);
}
}
///
/// Fires a Sync Failure event.
///
/// Exception object which caused the sync Failure
/// AsyncOptions object that controls whether
protected void FireSyncFailureEvent(Exception exception, AsyncOptions options)
{
if (options.ExecuteCallbackOnMainThread)
{
// Enqueue the callback so that the Unity main thread dispatcher
// can invoke the callback on the main thread.
UnityRequestQueue.Instance.ExecuteOnMainThread(() =>
{
FireSyncFailureEvent(exception);
});
}
else
{
FireSyncFailureEvent(exception);
}
}
}
}