package eu.hgross.blaubot.util;
import java.util.concurrent.atomic.AtomicBoolean;
import eu.hgross.blaubot.core.Blaubot;
import eu.hgross.blaubot.core.BlaubotKingdom;
import eu.hgross.blaubot.core.IBlaubotDevice;
import eu.hgross.blaubot.core.ILifecycleListener;
import eu.hgross.blaubot.admin.AbstractAdminMessage;
import eu.hgross.blaubot.admin.AddSubscriptionAdminMessage;
import eu.hgross.blaubot.admin.RemoveSubscriptionAdminMessage;
import eu.hgross.blaubot.messaging.IBlaubotAdminMessageListener;
/**
* Handles the state of a subscription using an AdminMessageListener and LifecycleListener.
* Has to be attached to the channelmanager/lifecycle dispatcher before start like this:
*
* watcher.registerWithBlaubot(myBlaubot)
* XOR
* watcher.registerWithBlaubotServer(myBlaubot)
*
* if a subscription was made, onSubscribed(..) is called.
* if a subscription is no longer valid, onUnsubscribed() is called.
*/
public abstract class SubscriptionWatcher implements ILifecycleListener, IBlaubotAdminMessageListener {
private final short channelId;
private AtomicBoolean subscribed = new AtomicBoolean(false);
private IBlaubotDevice ownDevice;
public SubscriptionWatcher(short channelId) {
this.channelId = channelId;
}
public void registerWithBlaubot(Blaubot blaubot) {
blaubot.getChannelManager().addAdminMessageListener(this);
blaubot.addLifecycleListener(this);
ownDevice = blaubot.getOwnDevice();
}
public void unregisterFromBlaubot(Blaubot blaubot) {
blaubot.getChannelManager().removeAdminMessageListener(this);
blaubot.removeLifecycleListener(this);
ownDevice = null;
}
public void registerWithBlaubotKingdom(BlaubotKingdom blaubotKingdom) {
// TODO: the blaubotKingdom needs a method to get to know when the kingdom was disconnected!
blaubotKingdom.addLifecycleListener(this);
blaubotKingdom.getChannelManager().addAdminMessageListener(this);
ownDevice = blaubotKingdom.getOwnDevice();
}
public void unregisterFromBlaubotKingdom(BlaubotKingdom blaubotKingdom) {
blaubotKingdom.removeLifecycleListener(this);
blaubotKingdom.getChannelManager().removeAdminMessageListener(this);
ownDevice = null;
}
@Override
public void onAdminMessage(AbstractAdminMessage adminMessage) {
final String ourUniqueDeviceId = ownDevice.getUniqueDeviceID();
if (adminMessage instanceof AddSubscriptionAdminMessage) {
final AddSubscriptionAdminMessage addSubscriptionAdminMessage = (AddSubscriptionAdminMessage) adminMessage;
final String uniqueDeviceId = addSubscriptionAdminMessage.getUniqueDeviceId();
final boolean ourUniqueId = uniqueDeviceId.equals(ourUniqueDeviceId);
final boolean ourChannel = addSubscriptionAdminMessage.getChannelId() == channelId;
if (ourChannel && ourUniqueId) {
subscribed.set(true);
onSubscribed(channelId);
}
} else if (adminMessage instanceof RemoveSubscriptionAdminMessage) {
final RemoveSubscriptionAdminMessage removeSubscriptionAdminMessage = (RemoveSubscriptionAdminMessage) adminMessage;
final boolean ourUniqueId = removeSubscriptionAdminMessage.getUniqueDeviceId().equals(ourUniqueDeviceId);
final boolean ourChannel = removeSubscriptionAdminMessage.getChannelId() == channelId;
if (ourChannel && ourUniqueId) {
subscribed.set(false);
onUnsubscribed(channelId);
}
}
}
/**
* Called when a subscription to the channel was made.
* @param channelId the channel id
*/
public abstract void onUnsubscribed(short channelId);
/**
* Called when the subscription was lost due to an unsubscribe or onDisconnected event
* @param channelId the channel id
*/
public abstract void onSubscribed(short channelId);
@Override
public void onConnected() {
}
@Override
public void onDisconnected() {
subscribed.set(false);
onUnsubscribed(channelId);
}
@Override
public void onDeviceJoined(IBlaubotDevice blaubotDevice) {
}
@Override
public void onDeviceLeft(IBlaubotDevice blaubotDevice) {
}
@Override
public void onPrinceDeviceChanged(IBlaubotDevice oldPrince, IBlaubotDevice newPrince) {
}
@Override
public void onKingDeviceChanged(IBlaubotDevice oldKing, IBlaubotDevice newKing) {
}
/**
* @return true, iff the registered instance is currently subscribed to the channel
*/
public boolean isSubscribed() {
return subscribed.get();
}
}