package co.smartreceipts.android.sync.network;
import android.support.annotation.NonNull;
import com.google.common.base.Preconditions;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import io.reactivex.Observable;
/**
* This class provides a simple mechanism to determine whether or not we're currently connected to one or more network
* types via a composite check
*
* @author Will Baumann
*/
public class CompositeNetworkProviderImpl implements NetworkProvider, NetworkStateChangeListener {
protected final List<NetworkProvider> mNetworkProviders;
private final NetworkStateChangeListenerTracker mNetworkStateChangeListenerTracker = new NetworkStateChangeListenerTracker();
private final AtomicBoolean mIsConnected = new AtomicBoolean(false);
public CompositeNetworkProviderImpl(@NonNull NetworkProvider... networkProviders) {
mNetworkProviders = new CopyOnWriteArrayList<>(Arrays.asList(Preconditions.checkNotNull(networkProviders)));
}
@Override
public synchronized void initialize() {
mIsConnected.set(isNetworkAvailable());
for (final NetworkProvider networkProvider : mNetworkProviders) {
networkProvider.initialize();
networkProvider.registerListener(this);
}
}
@Override
public synchronized void deinitialize() {
for (final NetworkProvider networkProvider : mNetworkProviders) {
networkProvider.deinitialize();
networkProvider.unregisterListener(this);
}
mIsConnected.set(false);
mNetworkStateChangeListenerTracker.clear();
}
@Override
public synchronized boolean isNetworkAvailable() {
boolean isNetworkAvailable = false;
for (final NetworkProvider networkProvider : mNetworkProviders) {
isNetworkAvailable = isNetworkAvailable || networkProvider.isNetworkAvailable();
}
return isNetworkAvailable;
}
@Override
public synchronized void registerListener(@NonNull NetworkStateChangeListener listener) {
mNetworkStateChangeListenerTracker.registerListener(listener);
}
@Override
public synchronized void unregisterListener(@NonNull NetworkStateChangeListener listener) {
mNetworkStateChangeListenerTracker.unregisterListener(listener);
}
@Override
public synchronized void onNetworkConnectivityLost() {
checkForConnectionChange();
}
@Override
public synchronized void onNetworkConnectivityGained() {
checkForConnectionChange();
}
@NonNull
public Observable<Boolean> getNetworkStateChangeObservable() {
return mNetworkStateChangeListenerTracker.getNetworkStateChangeObservable();
}
protected synchronized void checkForConnectionChange() {
final boolean hasConnection = isNetworkAvailable();
if (mIsConnected.compareAndSet(!hasConnection, hasConnection)) {
if (hasConnection) {
mNetworkStateChangeListenerTracker.notifyNetworkConnectivityGained();
} else {
mNetworkStateChangeListenerTracker.notifyNetworkConnectivityLost();
}
}
}
}