package com.novoda.bonfire.channel.database; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.novoda.bonfire.channel.data.model.Channel; import com.novoda.bonfire.rx.FirebaseObservableListeners; import com.novoda.bonfire.user.data.model.User; import java.util.ArrayList; import java.util.List; import rx.Observable; import rx.functions.Func1; import static com.novoda.bonfire.channel.database.ChannelConverter.fromFirebaseChannel; import static com.novoda.bonfire.channel.database.ChannelConverter.toFirebaseChannel; public class FirebaseChannelsDatabase implements ChannelsDatabase { private final DatabaseReference publicChannelsDB; private final DatabaseReference privateChannelsDB; private final DatabaseReference channelsDB; private final DatabaseReference ownersDB; private final FirebaseObservableListeners firebaseObservableListeners; public FirebaseChannelsDatabase(FirebaseDatabase firebaseDatabase, FirebaseObservableListeners firebaseObservableListeners) { this.publicChannelsDB = firebaseDatabase.getReference("public-channels-index"); this.privateChannelsDB = firebaseDatabase.getReference("private-channels-index"); this.channelsDB = firebaseDatabase.getReference("channels"); this.ownersDB = firebaseDatabase.getReference("owners"); this.firebaseObservableListeners = firebaseObservableListeners; } @Override public Observable<List<String>> observePublicChannelIds() { return firebaseObservableListeners.listenToValueEvents(publicChannelsDB, getKeys()); } @Override public Observable<List<String>> observePrivateChannelIdsFor(User user) { return firebaseObservableListeners.listenToValueEvents(privateChannelsDB.child(user.getId()), getKeys()); } @Override public Observable<Channel> readChannelFor(String channelName) { return firebaseObservableListeners.listenToSingleValueEvents(channelsDB.child(channelName), asChannel()); } @Override public Observable<Channel> writeChannel(Channel newChannel) { return firebaseObservableListeners.setValue(toFirebaseChannel(newChannel), channelsDB.child(newChannel.getName()), newChannel); } @Override public Observable<Channel> writeChannelToPublicChannelIndex(Channel newChannel) { return firebaseObservableListeners.setValue(true, publicChannelsDB.child(newChannel.getName()), newChannel); } @Override public Observable<Channel> addOwnerToPrivateChannel(User user, Channel channel) { return firebaseObservableListeners.setValue(true, ownersDB.child(channel.getName()).child(user.getId()), channel); } @Override public Observable<Channel> removeOwnerFromPrivateChannel(User user, Channel channel) { return firebaseObservableListeners.removeValue(ownersDB.child(channel.getName()).child(user.getId()), channel); } @Override public Observable<Channel> addChannelToUserPrivateChannelIndex(User user, Channel channel) { return firebaseObservableListeners.setValue(true, privateChannelsDB.child(user.getId()).child(channel.getName()), channel); } @Override public Observable<Channel> removeChannelFromUserPrivateChannelIndex(User user, Channel channel) { return firebaseObservableListeners.removeValue(privateChannelsDB.child(user.getId()).child(channel.getName()), channel); } @Override public Observable<List<String>> observeOwnerIdsFor(Channel channel) { return firebaseObservableListeners.listenToValueEvents(ownersDB.child(channel.getName()), getKeys()); } private static Func1<DataSnapshot, Channel> asChannel() { return new Func1<DataSnapshot, Channel>() { @Override public Channel call(DataSnapshot dataSnapshot) { return fromFirebaseChannel(dataSnapshot.getValue(FirebaseChannel.class)); } }; } private static Func1<DataSnapshot, List<String>> getKeys() { return new Func1<DataSnapshot, List<String>>() { @Override public List<String> call(DataSnapshot dataSnapshot) { List<String> keys = new ArrayList<>(); if (dataSnapshot.hasChildren()) { Iterable<DataSnapshot> children = dataSnapshot.getChildren(); for (DataSnapshot child : children) { keys.add(child.getKey()); } } return keys; } }; } }